1、什么是柯里化?
柯里化是把接受多個(gè)參數(shù)的函數(shù)變換成接受一個(gè)單一參數(shù)(最初函數(shù)的第一個(gè)參數(shù))的函數(shù)洒宝,并且返回接受余下的參數(shù)切返回結(jié)果的新函數(shù)的技術(shù)
用數(shù)學(xué)理解就是:一個(gè)函數(shù)求xy坷牛,當(dāng)傳入y=2時(shí),返回的就是2x
2躏将、簡單示例
例如:實(shí)現(xiàn)一個(gè)函數(shù),輸入的是任一整數(shù)考蕾,輸出要返回輸入的整數(shù)+2
一般的寫法是
func addTwo(_ a : Int)->Int{
return a+2
}
上面這種寫法就只是簡單的可以實(shí)現(xiàn)這個(gè)函數(shù)祸憋,并沒有進(jìn)行優(yōu)化,且不通用肖卧,里面的+2直接固定寫死了蚯窥,如果要實(shí)現(xiàn)+4/+6/+8欧瘪,不能每次都去重新定義一個(gè)函數(shù)富弦,我們需要定義一個(gè)通用的函數(shù)映屋,所以需要做如下改進(jìn)鹃两,主要利用的是swift的currying技術(shù)
func addTwo(_ a : Int)->(Int)->Int{
return {b in
return a+b
}
}
上面的函數(shù)可以簡化成
func addTwo(_ a : Int)->(Int)->Int{
return {b in a+b }
}
還可以更通用一些冗茸,將參數(shù)定義為泛型
//兩個(gè)參數(shù)的泛型
func curry<A, B>(_ function:@escaping (A)->B)->(A)->B{
return {a in function(a)}
}
//三個(gè)參數(shù)的泛型
func curry<A, B, C>(_ function:@escaping (A, B)->C)->(A)->(B)->C{
return {a in {b in function(a,b)}}
}
//四個(gè)參數(shù)的泛型
func curry<A, B, C, D>(_ function:@escaping (A, B, C)->D)->(A)->(B)->(C)->D{
return {a in {b in {c in function(a, b, c)}}}
}
//currying調(diào)用
func addTwo(_ a : Int, _ b : Int)->Int{
return a+b
}
let result = curry(addTwo)(1)(2) //打印的結(jié)果為3
3间涵、項(xiàng)目中的實(shí)際應(yīng)用
主要應(yīng)用在需要傳多個(gè)參數(shù)的函數(shù)南窗,
1)例如:假設(shè)有這樣一個(gè)需求撵渡,我需要記錄某個(gè)系統(tǒng)的日志牌里,日志需要包含以下幾個(gè)要素:操作人的名字name颊咬,時(shí)間time,日志類型type和日志內(nèi)容msg牡辽。
func curry<A, B, C, D, E>(_ function:@escaping (A, B, C, D)->E)->(A)->(B)->(C)->(D)->E{
return {a in {b in {c in {d in function(a, b, c, d)}}}}
}
func createLogInfo(_ name : String, _ time : String, _ type : String, _ msg : String)->String{
return "name : \(name)\n" + "type : \(type)\n" + ("message : \(msg)\n" + "time: \(time) ")
}
//調(diào)用
let createLogInfoResult = curry(createLogInfo)("functionName")("today")("Error")("somethingWrong")
輸出結(jié)果:
name : functionName
type : Error
message : somethingWrong
time: today
2)封裝target-action喳篇,對其安全的改造
原因:由于swift的selector智能是字符串生成,面臨難以重構(gòu)的問題态辛,并且無法在編譯期間檢查
改造的步驟:
(1)定義一個(gè)目標(biāo)事件協(xié)議
//目標(biāo)事件協(xié)議
protocol TargetAction {
func performAction()
}
(2)定義一個(gè)類麸澜,遵循(1)中的協(xié)議來處理事件
/**
OC中的委托
事件包裝結(jié)構(gòu),這里是泛型,這里表示傳入的數(shù)據(jù)類型可以是AnyObject
這個(gè)方法遵循TargetAction協(xié)議來處理事件
*/
struct TargetActionWrapper<T: AnyObject>:TargetAction {
weak var target : T?
//柯里化
let action : (T) -> () -> ()
func performAction() {
if let t = target {
action(t)()
}
}
}
(3)枚舉事件的類型
//枚舉
enum ControlEvent{
case TouchUpInside
case ValueChanged
//...
}
(4)示例
//示例
class currying{
var actions = [ControlEvent : TargetAction]()
func setTarget<T: AnyObject>(_ target : T, _ action : @escaping (T)->()->(), _ controlEvent : ControlEvent){
actions[controlEvent] = TargetActionWrapper(target: target, action: action)
print("T \(T.self)")
print("action \(action)")
}
//移除
func removeTargetForControlEvent(_ controlEvent : ControlEvent){
actions[controlEvent] = nil
}
//執(zhí)行
func performActionForControlEvent(_ controlEvent : ControlEvent){
actions[controlEvent]?.performAction()
}
}
(5)在項(xiàng)目中的實(shí)際使用
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
currying().setTarget(self, ViewController.btnclick, .TouchUpInside)
}
func btnclick(){
print("點(diǎn)擊了")
}
}