Swift 柯里化(Currying)

867 阅读2分钟

本篇并没有花费多大的精力整理查阅,仅仅是将Swift 必备 Tips书中的内容,写给大家看一下,对大家了解Swfit 柯里化是有比较大的帮助的!

Swift里可以将方法进行柯里化,也就是把接受多个参数的方法进行一些变形,使其更加灵活的方法。函数式的编程思想贯穿于Swift,而函数的柯里化正是Swift 语言函数式特点的重要表现。

举个例子,下面的函数简单地将输入的数字加1:

func addOne(num: Int) -> Int {
    return num + 1
}

这个函数所表达的内容非常有限,如果我们之后还需要一个将数字加2,或者加3的函数,可能不类似地去定义返回为num + 2 或者num + 3的版本。有没有更通用的方法呢?

我们其实可以定义一个通用的函数,它将接受需要与输入数字本身,然后进行操作:

func addTo(_ adder: Int) -> (Int) -> Int {
    return { num in
        return num + adder
    }
}

有了addTo,我们现在就能轻易写出像是addOne或者addTwo这样的函数啦:

let addTwo = addTo(2) //addTwo: (Int) -> Intlet result = addTwo(6)//result = 8

再举一个例子,我们可以创建一个比较大小的函数:

func greaterThan(_ comparer: Int) -> (Int) -> Bool {
    return {$0 > comparer}
}

let greaterThan10 = greaterThan(10)
greaterThan10(13)// => true
greaterThan10(8)// => false

柯里化是一种量产相似方法的好办法,可以通过柯里化一个方法模板来避免写出很多重复代码,也方便了今后维护。

拓展:

举一个实际运用的例子,在Swift中Selector只能使用字符串生成。这面临着一个很严重的问题,就是难以重构,并且无法再编译期间进行检查,这是非常危险的行为。但是Target-Action又是Cocoa如此重要的一项重要的设计模式,我们也可以采取利用方法的柯里化。

protocol TargetAction {
    func performAction()
}

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 Control{
    var actions = [ControlEvent: TargetAction]()
    func setTarget<T: AnyObject>(_ target: T, action: @escaping (T) -> () -> (), controlEvent: ControlEvent){
        action[controlEvent] = TargetActionWrapper(target: target, action: action)
    }
    func removeTargetForControlEvent(controlEvent: ControlEvent) {
        actions[controlEvent] = nil
    }

    func performActionForControlEvent(controlEvent: ControlEvent) {
        actions[controlEvent]?.performAction()
    }
}

使用方法:

class MyViewController {
    let button = Control()

    func viewDidLoad() {
        button.setTarget(self, action: MyViewController.onButtonTap, controlEvent: .touchUpInside)
    }

    func onButtonTap() {
        print("Button was tapped")
    }
}

上面就是柯里化的相关知识,大家可以使用起来撒,个人推荐Swift 必备 Tips这本书,扎实的基础功能永远是可靠的。