一. 干嘛的,举个例子
举个简单的例子,我们有一个需求,快速的拼接一个班级所有同学的姓名,性别,年龄及考试成绩,那么,按照一般的思路,我们要怎么实现呢?
方法实现:
@discardableResult
func studentInformation(name:String,gender:String,age:String,score:String) -> String {
return "姓名:"+name+"性别:"+gender+"年龄:"+age+"成绩:"+score
}
方法调用:
studentInformation(name: "小明", gender: "男", age: "15", score: "99")
studentInformation(name: "小红", gender: "女", age: "15", score: "98")
studentInformation(name: "小蓝", gender: "男", age: "14", score: "97")
studentInformation(name: "小花", gender: "女", age: "14", score: "93")
......
一个班级可能还好,几十个人,但如果是一个学校,甚至一个省市呢?这样调用方法费时费力还不好看。
而我们发现,性别无非是男或者女,年龄假设我们统计的都为同一个年级的,那么,也只有几个数字而已,那是不是写两个方法,每个性别一个方法呢?这样同样显得很蠢,这时候,我们就可以使用柯里化来方便的解决问题了:
方法实现:
@discardableResult
func studentInformation(gender: String)->(_ age: String)->(_ name: String,_ score:String)-> String {
return { (age: String)->(_ name: String,_ score:String)->String in
return {(name: String,_ score:String)->String in
return "姓名:"+name+"性别:"+gender+"年龄:"+age+"成绩:"+score
}
}
}
方法调用:
// 定义性别方法
let boy = studentInformation(gender: "男")
let girl = studentInformation(gender: "女")
// 定义不同性别的年龄方法
let boy14 = boy("14")
let boy15 = boy("15")
let girl14 = girl("14")
let girl15 = girl("15")
// 对象实例化,调用方法
let xm = boy15("小明","99")
let xh= girl15("小红","98")
let xl = boy14("小蓝","97")
let xhua= girl14("小花","93")
OK,使用场景已经介绍完了,那么,我们又该怎么理解函数柯里化呢?
我个人理解,柯里化函数,很像是一个工厂方法,只不过他生产出来的不是控件啊UI之类的,而是各种各样底层相同,部分参数重复率高的方法。比如我们举的这个例子,方法的底层都是对四个参数的拼接,而性别和年龄,是重复率高的参数。有了这些,我们看下柯里化的定义:
在计算机科学中,柯里化(Currying)又称部分求值(Partial Evaluation,是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数且返回结果的新函数的技术。
关键词:
1. 部分求值:
在调用柯里化函数的过程中,我们是将参数逐一传递给函数。而函数,根据所传入的参数,只会部分调用方法中的内容。比如,我们只传入性别的时候,方法是不会调用到下面这部分代码的,大家可以自己打断点调试
return {(name: String,_ score:String)->String in
return "姓名:"+name+"性别:"+gender+"年龄:"+age+"成绩:"+score
}
当然,我们也可以一口气把函数的所有参数都传进去,这样就类似链式编程了:
// 祭出老学长李雷
let liLei = studentInformation(gender: "男")("48")("李雷", "100")
使用注意:
1. 柯里化函数的参数必须按顺序调用,所以我们必须安排好参数的顺序。重复率高的参数放在前面例,如性别和年龄,重复率低的放在后面,如姓名和年龄
2. 柯里化函数代码只会调用一次,比如 let boy14 = boy("14")时调用到了return {(name: String,_ score:String)->String in这一行,那么在 let xl = boy14("小蓝","97")就不会再次调用这一行,而是直接执行return "姓名:"+name+"性别:"+gender+"年龄:"+age+"成绩:"+score,这个大家可以自己打断点测试一下
参考文章:
【Swift之柯里化函数(精品)】| 那些人追的干货
Swift中的函数柯里化(Function Currying)