浅谈 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),而是分成了多个括号
上面这段代码简单,但是下面这段代码 就不是很容易理解了。借鉴自: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
利用柯里化我们可以这么写:
仔细观察,我们发现depositor 没有实例化一个BankAccout对象,而是直接引用他的deposit方法,这就类似于C语言的函数指针。然后通过 给depositor传入一个实例化对象,返回一个 完整的deposit(Double)函数,然后 传入一个Double,返回空。
拆开depositor我们 可以这么写:
let depositor: BankAccount -> (Double) -> ()
分成两部分来看,第一部分:
以下是代码:
/// 目标事件协议
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 会 在不久移除 柯里化 这种 申明语法,推荐使用简单的多参数设计。当然, 即使 要去掉,这种 有趣的知识, 也是值得学习的
。
继续说柯里化
:
先理解柯里化:把接受多个参数的方法变换成接受第一个参数的方法,并且 返回接受余下的参数并返回结果的新方法。用数学的思维很好理解,一个函数 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 会 在不久移除 柯里化 这种 申明语法,推荐使用简单的多参数设计。当然, 即使 要去掉,这种 有趣的知识, 也是值得学习的
。
相关文章推荐
- Swift 柯里化(Currying)
- Swift 柯里化(Currying)
- Swift Currying(柯里化)
- Swift 柯里化(currying)和反柯里化(uncurrying)
- Swift柯里化(Currying)
- currying in javascript-js柯里化
- 函数式编程概念:柯里化(currying)
- 浅谈swift中的函数类型和闭包
- 浅谈Swift和OC的区别
- Swift中的柯里化函数
- 柯里化(currying)
- 浅谈Swift和Objective-C之间的那点事。。。
- 浅谈Swift语法
- 偏函数应用(Partial Application)和函数柯里化(Currying)
- 深入理解scala的柯里化( currying or curry )以及其用处
- 浅谈JavaScript中的柯里化函数
- Currying-柯里化[Swift笔记]
- 浅谈Swift语法
- Swift 浅谈Struct与Class
- JS中的柯里化(currying)