swift——复合类型——函数——闭包

闭包

闭包,closure,类似于oc中block及其他语言中lambda
闭包三种形式:
  • 全局函数:有名字,不捕获值
  • 嵌套函数:有名字,从外围函数捕获值
  • 闭包表达式:无名字,从上下文捕获值

闭包表达式

嵌套函数

func compare(a: Int, _ b: Int, _ cmp: (Int, Int) -> Bool) -> Int
{
    return cmp(a, b) ? a : b
}

func use_compare()
{
    func cmp(a: Int, b: Int) -> Bool
    {
        return a > b
    }
    
    let result = compare(8, 5, cmp)
    print("result = \(result)")
}

完整闭包表达式

func compare(a: Int, _ b: Int, _ cmp: (Int, Int) -> Bool) -> Int
{
    return cmp(a, b) ? a : b
}

func use_compare()
{
    let result = compare(8, 5, { (a: Int, b: Int) -> Bool in return a > b })
    print("result = \(result)")
}
总结:
  • 完整闭包表达式包括参数类型,参数名,返回类型,函数体(以in起始),闭包表达式包括在{}中,与嵌套函数相比,omit了函数名和argument label
  • let cmp: (Int, Int) -> Bool = { (a: Int, b: Int) -> Bool in return a > b }是合法的,只要参数类型和返回类型一致,显然闭包表达式类型为函数类型

类型推断

func compare(a: Int, _ b: Int, _ cmp: (Int, Int) -> Bool) -> Int
{
    return cmp(a, b) ? a : b
}

func use_compare()
{
    let result = compare(8, 5, { a, b in return a > b })
    print("result = \(result)")
}
总结:
  • 闭包表达式赋值给函数类型时,可omit参数类型以及返回类型,进一步可omit包围参数名的圆括号,因为可从函数类型推断出闭包表达式参数类型和返回类型
  • let cmp: (Int, Int) -> Bool = { a, b in return a > b }是合法的,可从左值函数类型推断出右值闭包表达式参数类型和返回类型

隐式return

func compare(a: Int, _ b: Int, _ cmp: (Int, Int) -> Bool) -> Int
{
    return cmp(a, b) ? a : b
}

func use_compare()
{
    let result = compare(8, 5, { a, b in a > b })
    print("result = \(result)")
}
总结:
  • 只有唯一一条表达式的闭包表达式可omit return,闭包表达式把唯一一条表达式值作为闭包表达式返回值隐式返回
  • let cmp: (Int, Int) -> Bool = { a, b in a > b }是合法的,唯一一条表达式值作为闭包表达式返回值隐式返回

形参速记

func compare(a: Int, _ b: Int, _ cmp: (Int, Int) -> Bool) -> Int
{
    return cmp(a, b) ? a : b
}

func use_compare()
{
    let result = compare(8, 5, { $0 > $1 })
    print("result = \(result)")
}
总结:
  • 可进一步omit形参名(包括in),使用形参速记$0,$1等,从0起始
  • let cmp: (Int, Int) -> Bool = { $0 > $1 }

操作符重载

func compare(a: Int, _ b: Int, _ cmp: (Int, Int) -> Bool) -> Int
{
    return cmp(a, b) ? a : b
}

func use_compare()
{
    let result = compare(8, 5, >)
    print("result = \(result)")
}
总结:
  • 如果参数类型支持相应的操作符重载,可omit参数,只保留重载的操作符
  • let cmp: (Int, Int) -> Bool = >非法

拖尾闭包

func compare(a: Int, _ b: Int, cmp: (Int, Int) -> Bool) -> Int
{
    return cmp(a, b) ? a : b
}

func use_compare()
{
    let result = compare(8, 5) { (a: Int, b: Int) -> Bool in return a > b }
    print("result = \(result)")
}
总结:
  • 如果最后一个参数是函数类型(包括只有一个参数),实参使用闭包表达式传时,可直接把闭包表达式写在函数调用后面,并且可omit该参数argument label,当闭包表达式比较长时使用拖尾闭包增强代码可读性

捕获值

嵌套函数捕获

func makeIncrementer(forIncrement amount: Int) -> () -> Int
{
    var runningTotal = 0
    
    func incrementer() -> Int
    {
        runningTotal += amount
        return runningTotal
    }
    
    return incrementer
}

func nestedFuncCapture()
{
    let incrementBy5 = makeIncrementer(forIncrement: 5)
    let incrementBy8 = makeIncrementer(forIncrement: 8);
    
    print(incrementBy5())
    print(incrementBy5())
    print(incrementBy5())
    
    print(incrementBy8())
    print(incrementBy8())
    print(incrementBy8())
}
output:
5
10
15
8
16
24
总结:
  • 可把嵌套函数理解为外围函数定义的局部对象,因此两次返回的嵌套函数指向的不是同一个函数对象,它们相互独立,互不影响
  • 嵌套函数捕获外围函数对象(参数对象和局部对象)理解为嵌套函数保存了指向这些对象的引用,嵌套函数被调用时才获取这些对象值
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值