Swift:类型推断

我要坦白。 我真的对在我的代码中各处编写iflet和guard感到厌倦。 我看到一些真正的基本问题:

  • 您正在与Swift斗争,而不是表达需要完成的工作;
  • 您没有到强制转换代码的中央访问点;
  • 您对Swift API的更改不满意。
  • 您必须编写更多代码,自动完成功能将无法为您节省$
  • 您不使用类型推断。

首先,让我介绍一下我使用的强制转换功能:

是的,那只是上面的包装 。 为什么好呢? 它允许在不考虑Swift的预处理限制的情况下转换为类型,而Swift的预处理限制仅出于帮助开发人员的原因而创建,这些限制对类型一无所知。 一个很好的例子是Int? 要转换为Int?的类型(是的,可选的包装在可选的包装中,您没有误读)。 猜猜是什么,编译器不会让您用as那样

编译器失败,并从’Int ?? 到“诠释?” 仅解包可选; 您是要使用’!’吗? 。 这意味着,编译器可以做到这一点,但是,它认为它更了解程序员想要什么,因此它试图通过强调,通过展开Int来提供帮助。 进入Int? 我们收到Optional 作为结果。 哦,非常感谢你,Obvious上尉,没有您的宝贵帮助我们就无法猜到。

因此,另一种解决方案是使用泛型类型。 您可以从Swift本身的角度(如果我们可以禁用程序员的健全性检查)来看,泛型中的类型可以是任何类型,包括函数,可选,数组或其他任何类型。 而且,你猜对了, 诠释? 以及诠释? 也是分开的类型。 而且, 作为? 本身可以用于解包(尽管我理解为什么强制转换可能导致解包的原因,而AST和SIL都没有提供这种行为的任何线索)。 因此,如果我们看一下上面的强制转换函数,是否要强制转换并从Int中解包 输入Int? ,我们可以这样写:

这将向我们显示:Optional(1)。 另一方面,如果我们尝试转换Int? 转换为Int类型的系统将按预期方式运行,并且不会打印任何内容:

但是,这种功能尽管是类型推断(启用并可链接),但就您必须编写的代码量而言,并不是特别有用。 可以通过使用函子,应用函数或单子函数来缓解这种情况。 我可以承认,我正在迈入函数式编程的第一步,因此,在设法掌握FP背后的思想以及如何将它们与OOP可变状态混合后,我将在以后的博客文章中介绍这些类型。在一个友好的功能社区的帮助下(对所有的lispers和haskellers表示敬意,他们回答了我的愚蠢问题,并编写了免费的开源书籍,以简单的方式解释了困难的概念,你们是最棒的,伙计们)。 现在,让我们以简单不正确的方式定义这些类型:

  • Functor —类型,谁实现地图
  • 适用性-类型,实施者;
  • Monads —类型,谁实现flatMap

因此,让我们来解决一个现实生活中的问题。 假设我们有一个Int属性,并且想要将Any放进去,如果它的值可以转换为Int

我们不能直接将Any值分配给Int属性,因此我们应该使用iflet或guard来展开:

具有objc背景的人的代码量(过去一直为nil为有效值)令人震惊。 此外,别忘了,您不能直接将消息发送到包装在Optional中的值,这与objc不同,在objc中,这是有效操作(除非您发送消息,而结果是结构)。 在这种情况下,我们的转换功能将如何提供帮助?

这样做要好得多,而且,只要您还记得, cast可以返回Optional ,那么此代码将更具表现力。 总体而言,即使您不这样做,只要您至少记得映射是什么(如果值合法,则将函数应用于包装的值),该代码仍会具有表达力。 那种情况下的所有类型都是在没有任何外部指导的情况下由编译器推断的,因此我们可以编写更简单,更轻量的类型安全代码,且语法不那么冗长。

仍然,想象一下为每种单元格类型编写这样的强制类型转换,就像我们之前的示例一样。 冗长而令人讨厌的语法的重复和挣扎正在等待着我们。 这远非DRY我们都尝试遵守(我们确实尝试这样做,不是吗?)。 而且,还有一个明显的缺陷:除非您膨胀代码,否则强制转换是不可链接的。

上面的转换+地图+赋值的结果()? (或Void ? ,如果您更习惯的话)。 这意味着,连续的第二张地图对我们没有任何好处,因为我们实际上无法对unwrapped ()做任何有用的事情。

但这是另一天的故事。 在我的下一篇文章中,我们将深入探讨如何使铸件可链接。

转换功能在cocoapods IDPCastable可用,在github上也可用:IDPCastable。

就是这样,伙计们。 祝您有美好的一天,无论您身在何处,都要保持干燥。