您的位置:首页 > 移动开发 > Swift

浅谈 Swift 柯里化(Currying)

2016-08-18 17:09 651 查看
       在 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 会 在不久移除 柯里化 这种 申明语法,推荐使用简单的多参数设计。当然, 即使 要去掉,这种 有趣的知识, 也是值得学习的

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  ios 柯里化 Swift