【问题标题】:Understanding closures - capturing values了解闭包 - 捕获值
【发布时间】:2020-12-13 15:48:37
【问题描述】:

在 The Swift Programming Language doc, Closures, "Capturing Values" 中有以下例子:

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

我遵循描述,除了为什么第一次调用 makeIncrementer 时 runningTotal 只初始化为 0。该文档显示以下内容:

let incrementByTen = makeIncrementer(forIncrement: 10)
incrementByTen()
// returns a value of 10
incrementByTen()
// returns a value of 20
incrementByTen()
// returns a value of 30

为什么每次调用 incrementByTen 时 runningTotal 不重置为 0?

【问题讨论】:

  • 因为它被捕获了。这就是例子的重点!这就是闭包

标签: swift closures


【解决方案1】:

这是关于范围的一堂很好的课程,因为它正在捕获。在原始示例中,runningTotal 超出了incrementer() 的范围,incrementer() 已捕获此值。如果将runningTotal 放在incrementer() 中,更改其范围,则每次调用时输出都将重置为0,因为runningTotal 现在是本地范围的,并且它的值不会保留在函数之外——这里没有捕获任何内容.

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

let incrementByTen = makeIncrementer(forIncrement: 10)
incrementByTen() // 10
incrementByTen() // 10
incrementByTen() // 10

假设runningTotal 是一个全局变量,声明在一切之外。现在应该清楚为什么每次调用函数时都不会重置该值。但是对于incrementer(),这个范围与原始示例没有什么不同。在这两种情况下,runningTotal 都是它捕获的函数范围之外的变量。

var runningTotal = 0 // global

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

let incrementByTen = makeIncrementer(forIncrement: 10)
incrementByTen() // 10
incrementByTen() // 20
incrementByTen() // 30

【讨论】:

  • 感谢您的详细解释。非常有助于理解这一切是如何发生的。
【解决方案2】:

看返回值:

makeIncrementer返回incrementer,内部函数amountrunningTotal被捕获,runningTotal被设置一次。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-01-24
    相关资源
    最近更新 更多