功能性Swift-咖喱
在使用Swift时,我在函数式编程环境中进行了越来越深入的研究。
在其他编程语言(例如Python或Haskell)中使用的许多技术可以迅速获得。
今天,我想向您介绍其中一种,称为currying。
Swift是一种出色的编程语言,它利用了函数式编程的优势。
函数式编程的主要好处之一是函数是高阶公民,这意味着迅速使用函数可以执行以下操作之一:
- 将一个或多个函数作为参数
- 返回一个函数作为参数
最近,我在函数程序员Curry中发现了一种众所周知的技术。
Currying用于将具有多个参数的函数分解为一系列包含参数的函数。
当您想提高代码的可读性和可重用性时,此技术变得非常有用。
该函数如下所示:
如您所见,咖喱是一个简单的功能。
它以一个函数作为参数( fn ) 首先返回一个函数 ,该函数采用传入参数的函数的第一个参数传递给curry(此处为A ):
(a: A) -> (B) -> C
然后,它返回一个函数 ,该函数采用传递给curry的函数的第二个参数(此处为B ):
-
(b: B) -> C
最后,使用参数A和B调用作为参数传递的函数 :
- fn (a,b)
值得注意的是,函数fn仅在最后一个参数传递给curried方法时才计算 。
在某些情况下,此方法可能有用,其中一种情况是您希望使现有方法更方便或可重复使用:
让我们采用以下日志方法:
使用两个参数调用它可能变得很乏味,使用curry我们可以使它可重用且更明确,而无需创建一个封装参数的新函数。
充分利用高阶函数的优势,我们可以分解logMessage并创建一个变量,该变量是一个将日志消息作为参数的函数,然后将其记录在调试级别。
另一个用途是利用诸如map , forEach等功能性方法。
让我们来看下面的例子:
如您所见,使用currying可以很容易地部分应用任何方法。
(Vincent Pradeilles在我当时所在的CocoaHeads展示了这种用咖喱粉的用例。)
如果您正在使用RxSwift或计划使用它,您可能想知道如何将使用completionBlock的异步代码迁移到一系列Observable。
重构所有代码库只是为了使其可观察而不是(completionBlock /成功和失败块)通常是不可行的。
使用curry和扩展,您几乎不需要代码即可实现。
第一个fromAsync方法将一个函数作为参数,该函数将completionBlock作为唯一参数。 该方法将处理转换为Observable的方法 。
其他两种方法的工作原理完全相同,只是它们使用curring分解参数并返回第一个fromAsync方法。
第一个用于转换具有一个参数和一个completionBlock的方法。
最后一个用于转换带有两个参数和一个completionBlock的方法。