美文网首页
Swift-Currying(柯里化)

Swift-Currying(柯里化)

作者: Style_月月 | 来源:发表于2020-07-14 00:10 被阅读0次

    1、什么是柯里化?

    柯里化是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数切返回结果的新函数的技术

    用数学理解就是:一个函数求xy,当传入y=2时,返回的就是2x

    2、简单示例

    例如:实现一个函数,输入的是任一整数,输出要返回输入的整数+2

    一般的写法是

    func addTwo(_ a : Int)->Int{
            return a+2
        }
    
    image.gif

    上面这种写法就只是简单的可以实现这个函数,并没有进行优化,且不通用,里面的+2直接固定写死了,如果要实现+4/+6/+8,不能每次都去重新定义一个函数,我们需要定义一个通用的函数,所以需要做如下改进,主要利用的是swift的currying技术

    func addTwo(_ a : Int)->(Int)->Int{
            return {b in
                return a+b
            }
        }
    
    image.gif

    上面的函数可以简化成

    func addTwo(_ a : Int)->(Int)->Int{
            return {b in a+b }
        }
    
    image.gif

    还可以更通用一些,将参数定义为泛型

        //两个参数的泛型
        func curry<A, B>(_ function:@escaping (A)->B)->(A)->B{
            return {a in function(a)}
        }
        //三个参数的泛型
        func curry<A, B, C>(_ function:@escaping (A, B)->C)->(A)->(B)->C{
            return {a in {b in function(a,b)}}
        }
        //四个参数的泛型
        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调用
        func addTwo(_ a : Int, _ b : Int)->Int{
            return a+b
        }
    
        let result = curry(addTwo)(1)(2) //打印的结果为3
    
    image.gif

    3、项目中的实际应用

    主要应用在需要传多个参数的函数,

    1)例如:假设有这样一个需求,我需要记录某个系统的日志,日志需要包含以下几个要素:操作人的名字name,时间time,日志类型type和日志内容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)    ")
        }
    
        //调用
        let createLogInfoResult = curry(createLogInfo)("functionName")("today")("Error")("somethingWrong")
    
    输出结果:
    name : functionName
    type : Error
    message : somethingWrong
    time: today
    
    image.gif

    2)封装target-action,对其安全的改造

    原因:由于swift的selector智能是字符串生成,面临难以重构的问题,并且无法在编译期间检查

    改造的步骤:

    (1)定义一个目标事件协议

    //目标事件协议
    protocol TargetAction {
        func performAction()
    }
    
    image.gif

    (2)定义一个类,遵循(1)中的协议来处理事件

    /**
    
     OC中的委托
    
     事件包装结构,这里是泛型,这里表示传入的数据类型可以是AnyObject
    
     这个方法遵循TargetAction协议来处理事件
    
     */
    
    struct TargetActionWrapper<T: AnyObject>:TargetAction {
    
        weak var target : T?
    
        //柯里化
        let action : (T) -> () -> ()
    
        func performAction() {
            if let t = target {
                action(t)()
            }
        }
    }
    
    image.gif

    (3)枚举事件的类型

    //枚举
    enum ControlEvent{
        case TouchUpInside
        case ValueChanged
        //...
    }
    
    image.gif

    (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
        }
    
        //执行
        func performActionForControlEvent(_ controlEvent : ControlEvent){
            actions[controlEvent]?.performAction()
        }
    }
    
    image.gif

    (5)在项目中的实际使用

    class ViewController: UIViewController {
    
        override func viewDidLoad() {
            super.viewDidLoad()
    
            currying().setTarget(self, ViewController.btnclick, .TouchUpInside)
    
        }
    
         func btnclick(){
            print("点击了")
        }
    }
    
    image.gif

    相关文章

      网友评论

          本文标题:Swift-Currying(柯里化)

          本文链接:https://www.haomeiwen.com/subject/vqmthktx.html