在 Swifter中,第一章 就是 讲解 柯里化。这本书 真的是非常的不错,值得一看,同时,正如作者王巍所说,国内的 大量的流水线书籍真的没必要买。如果 你希望入门,去这里,如果 你想提高,我非常推荐这本书。当然 你也可以在这里找到它的内容。
继续说柯里化:
先理解柯里化:把接受多个参数的方法变换成接受第一个参数的方法,并且 返回接受余下的参数并返回结果的新方法。用数学的思维很好理解,一个函数 xy ,当 传入 y = 2,返回的 就是 2x。
写一个简单的例子。
func JustForExample(a:Int)(b:Int) -> Int{
return a + b
}
这个方法需要传入两个参数,但是我们没有写成 (a:Int,b:Int),而是分成了多个括号
func exampleUse() {
let exampleAdd = JustForExample(3) //只传入第一个参数,返回一个函数,函数为 Int ->Int
let result = exampleAdd(b:7)//传入 Int 返回 Int
print(result)
}
这就是柯里化的简单应用,当然 柯里化 在 js 等 中 也是很常用的。
上面这段代码简单,但是下面这段代码 就不是很容易理解了。借鉴自: Ole Begemann
class BankAccount {
var balance: Double = 0.0
func deposit(amount: Double) {
balance += amount
}
}
定义了一个class,其中有一个方法 deposit(Double),
正常使用:
let account = BankAccount()
account.deposit(100) // balance = now
利用柯里化我们可以这么写:
let depositor = BankAccount.deposit
depositor(account)(100) // balance = 200
仔细观察,我们发现depositor 没有实例化一个BankAccout对象,而是直接引用他的deposit方法,这就类似于C语言的函数指针。然后通过 给depositor传入一个实例化对象,返回一个 完整的deposit(Double)函数,然后 传入一个Double,返回空。
拆开depositor我们 可以这么写:
let depositor: BankAccount -> (Double) -> ()
分成两部分来看,第一部分:
BankAccount -> (Double) 传入一个 BankAccount实例,返回一个需要传入Double的Function,
第二部分:
(Double) -> () 传入一个Double,返回 空,你应该理解为对 deposit() 的签名。
然后是 原文照着这个思路 ,借助柯里化 ,对target-acton的安全的改造。(因为 Swift的Selector 只能以字符串生成,面临难以重构的问题,并且无法再编译期间检查)。
以下是代码:
/// 目标事件协议
protocol TargetAction {
func performAction()
}
/**
OC中的委托
事件包装结构,这里是泛型,这里表示传入的数据类型可以是AnyObject
这个方法遵循TargetAction协议来处理事件
*/
struct TargetActionWrapper<T: AnyObject>:TargetAction{
weak var target: T?
//柯里化
let action: (T) -> () -> ()
func performAction() -> () {
if let t = target {
action(t)()
}
}
}
/// 枚举事件
enum ControlEvent {
case TouchUpInside
case ValueChanged
//...
}
/// 例子
class currying{
var actions = [ControlEvent :TargetAction]()
func setTarget<T:AnyObject>(target: T,action: (T) -> () -> (),controlEvent:ControlEvent){
actions[controlEvent] = TargetActionWrapper(target:target,action:action)
print(T)
print(action)
}
/// 移除
func removeTargetForControlEvent(controlEvent:ControlEvent){
actions[controlEvent] = nil
}
/// 执行
func performActionForControlEvent(controlEvent:ControlEvent){
actions[controlEvent]?.performAction()
}
}
使用:
class ViewController: UIViewController {
let button = currying()
override func viewDidLoad() {
super.viewDidLoad()
button.setTarget(self, action: ViewController.onButtonTap, controlEvent: .TouchUpInside)
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func onButtonTap(){
}
func exampleUse() {
let exampleAdd = JustForExample(3) //只传入第一个参数,返回一个函数,函数为 Int ->Int
let result = exampleAdd(b:7)//传入 Int 返回 Int
print(result)
}
func JustForExample(a:Int)(b:Int) -> Int{
return a + b
}
}
写在最后:
不知道为什么,在你写上面的example的时候,会告诉你,Swift 会 在不久移除 柯里化 这种 申明语法,推荐使用简单的多参数设计。当然, 即使 要去掉,这种 有趣的知识, 也是值得学习的。