在计算机科学中,柯里化(Currying)是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数且返回结果的新函数的技术。
在Swift中你能够重写一个带多个参数的函数变成带一个参数的函数并且返回函数.返回的函数将继续带一个参数并返回另一个函数,如此循环一直到函数没有参数为止,最后函数所返回的值跟最初原函数(及带多个参数的函数)的值一样!,重写函数就称之为柯里化函数.
柯里化 (Currying)的中心思想就是把接受多个参数的方法进行一些变形,使方法的使用更加灵活。
举个例子,下面的函数简单地将对输入的数字实现加 1操作:
func add(_ num: Int) -> Int {
return num + 1
}
这个函数所表达的内容非常有限,如果我们之后还需要一个将输入数字加2,或者加3的函数, 可能不得不类似地去定义返回为num + 2,num + 3的函数。 这样就写了太多相关的代码,那么有没有更通用的方法呢?其实我们可以定义一个通用的函数,它将接受需要与输入数字相加的数,并返回一个函数(其实就是闭包)。返回的函数将接受输入数字本身,然后进行操作:
func addTo(_ adder: Int) -> (Int) -> Int {
return { num in
return num + adder
}
}
有了addTo函数,我们现在就能轻易写出像是加1,加2,加3等这样的函数了:
let addThree = addTo(3) //(Int) -> Int
let result = addThree(6) //9
再看一个例子,创建一个比较大小的函数:
func greaterThan(_ compare: Int) -> (Int) ->Bool {
return { $0 > compare }
}
let greaterThan10 = greaterThan(10)
greaterThan10(15) //true
greaterThan10(7) //false
由上面,我们也可以看到,使用了柯里化能够很好的帮助我们创建模版方法避免写重复的代码,也方便维护。
class BankAccount {
var balance: Double = 0.0
func deposit(_ amount: Double) {
balance += amount
}
}
接下来,我们存100,那么像正常使用类一样,如下:
//创建实例,调用方法
let account = BankAccount()
account.deposit(100)
print(account.balance) // balance is now 100
但是,我们也可以这样实现存储功能
let depositor = BankAccount.deposit
depositor(account)(100)
print(account.balance) // balance is now 200
上面二种方式实现功能完成是等同的。那么为什么我们可以这样使用呢?对于第二种使用方法,我们首先赋值了一个方法给depositor变量。使用 BankAccount.deposit并不是调用deposit方法,如果是调用方法,那么会出错的,因为需要实例对象才可以调用实例丰富。但是这里,我们仅仅是引用它。第二步才是真正的调用depositor方法,现在depositor的形式其实是这样的:
let depositor: BankAccount -> (Double) -> ()
换句话说,这个函数有一个单一的参数BankAccount实例,并且返回一个函数。返回的函数拥有一个Double类型的参数。那么我们就可以近一步简化代码:
BankAccount.deposit(account)(100)
print(account.balance) // balance is now 300
是不是有点意思。参考