如何在Swift中实现自己的Optional Chaining

深入了解.map和.flatMap运算符

自从我开始使用Swift进行编程以来,我不禁在对数组执行各种操作时使用mapreducefilter等函数。 关于它们的事情是如此令人愉快,以至于我永远不会错过将我通常的数组处理例程变成这些漂亮的函数运算符链的机会。 但是,如果我告诉您可以将这一概念的使用范围扩展到集合类型之外呢?

对于您来说,这可能不是什么大新闻,但您可以将map运算符与Optional类型一起使用。

没有什么比老的“ Hello world”更好地说明编码问题了。 这是一个接受字符串并以“ Hello”为前缀的函数:

  1. map用于将可选值转换为另一个值(可能也是不同类型)。 如果可选值中有一个值,那么它将遍历整个转换链。 如果不是,它将继续返回nil 。 简单。
  2. map用于将一个可选值转换为另一个可选值。 nil的行为不会改变,但是对于非nil值,其他所有转换都会增加一层嵌套,例如,您将从.some(T)转到.some(.some(U)) ,然后.some(.some(.some(V)))等。
  3. 就像前面的示例一样, flatMap用于将值转换为另一个可选值。 但是,每个新层都被“展平”到当前级别,因此最后只剩下一个Optional对象。 类似于保龄球从车道上掉下来并不断滚滚落下,一旦该值变为nil所有后续转换都将被忽略,并且一直保持nil直到链结束。

希望这可以使您更好地了解这些功能的行为方式以及它们为您带来的好处。 您可能还会注意到,此概念经常针对各种数据类型实现。 例如,一种非常流行的Result类型,广泛用作来自网络请求的值和错误的容器。 许多实现(例如这种实现)也支持mapflatMap功能。

但是,等等,还有更多。 再次查看图片,特别是flatMap部分。 这种行为会让您想起某些事情吗? 执行会沿着可选值的链进行下去,直到成功完成或达到nil为止。 如果您考虑一下,“可选链接”的工作方式完全相同。 因此,必须有一种方法可以仅使用mapflatMap运算符提出我们自己的Optional Chaining实现。

假设我们不使用转换函数,而是要访问某些属性。 从Swift版本4开始,我们可以通过传递属性名称作为函数参数来使用KeyPath语法来访问属性。 然后,我们将使用flatMap读取可选属性并map以访问非可选属性。 为了模仿原始语法,我们将编写一个扩展名并使用最喜欢的某个运算符,即~> 。 扩展名如下所示:

借助方法重写的强大功能,我们在处理普通变量和可选变量时都可以使用相同的方法签名,这将导致语法均匀,因此使用这些运算符的人将不必知道底层的方法。

试试看! 此新运算符可以用作内置链接语法的替代方法。 像这样:

几乎没有区别,您可以互换使用它们!

如您所见,“可选链接”并不是什么魔术,而仅仅是一种语法糖,它是一种机制的糖,您可以使用高阶函数的功能自行实现该机制。 现在,您知道了如何利用mapflatMap来编写更多声明性代码,并且已经准备好处理RxSwift之类的功能范例。

不要忘记Swift是开源的! 如果您想了解更多信息,可以自己研究Optional类型的源代码。

编码愉快!

Interesting Posts