浅谈 Swift 柯里化(Currying)

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



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值