【问题标题】:How do closures capture values from previous calls?闭包如何从以前的调用中捕获值?
【发布时间】:2016-10-16 18:43:30
【问题描述】:
typealias IntMaker = (Void)->Int

func makeCounter() ->IntMaker{
    var n = 0 // Line A

    func adder()->Integer{
        n = n + 1
        return n 
    }
    return adder
}

let counter1 = makeCounter()

counter1() // returns 1
counter1() // returns 2
counter1() // returns 3

不是每次调用counter1() 时都会调用“A 行”吗?意味着每次都应该调用var n = 0...

为什么计数器返回不同的值?他们不应该总是返回“1”吗?

【问题讨论】:

    标签: swift closures nested-function


    【解决方案1】:

    显然,每次调用 counter1 时, 都不会调用 A 行。

    事件的顺序是:

    • makeCounter 被调用,它声明和初始化n(A 行),定义adder,并在包含n 的上下文中返回adder 已经定义和初始化为 1。

    • 正是这个刚刚返回的函数被分配给counter1。因为 A 行不是该函数 (adder/counter1) 的一部分,所以在调用该函数时它不会被执行。

    • counter1 的每次调用都在相同的上下文中执行,这就是n 在调用中保留其值的原因:它们都在访问相同的n

    【讨论】:

    • 1) 你的第二个项目符号,“this”这个词指的是什么?能否请您进行编辑。 2) 我的问题是为什么上下文不是从var n = 0 开始的,为什么它只从函数调用开始?你说的是我确实知道的。我不知道为什么会这样!
    • "this" 是函数adder。上下文不是运行的代码,而是代码创建和初始化的变量。 var n = 0 不是上下文的一部分,变量 n 初始化为 0 是。
    【解决方案2】:

    您曾致电makeCounter() 一次。这将创建您的新闭包,并将其分配给counter1。这个闭包关闭了可变的var n,并且只要这个闭包存在就会一直被捕获。

    调用counter1() 将执行它,但它会保留相同的捕获n,并对其进行变异。这个特殊的“加法器”将始终捕获相同的n,只要它存在..

    要获得您建议的行为,您需要创建新的闭包来捕获 n 的新实例:

    let counter1 = makeCounter()
    
    counter1() // returns 1
    counter1() // returns 2
    counter1() // returns 3
    
    var counter2 = makeCounter()
    counter2() // returns 1
    counter2 = makeCounter()
    counter2() // returns 1
    counter2 = makeCounter()
    counter2() // returns 1
    

    现在counter1counter2 都有各自独立的n 实例。

    【讨论】:

    • 每次拨打电话时如何重置一个值?也许知道这会帮助我更好地理解
    • 您需要再次使用makeCounter() 进行新的关闭。在调用makeCounter() 期间,将创建一个新的n 变量,并且一个新的闭包将捕获该新的n。那么
    • 闭包的全部意义在于引用语义。如果您想要值语义,您可以将 n 作为参数传递给闭包。这将使n 的副本成为闭包的本地副本,并且独立于外部副本。
    • A 行是makeCounter 的一部分;它不是adder/counter1的一部分。
    • @Honey Line A 只在执行过程中被调用makeCounter() Line A 生成一个新的var n,它完成了,结束了。在您再次拨打makeCounter() 之前,A 行是无关紧要的。闭包只是捕获了恰好在 A 行之后存在的n
    猜你喜欢
    • 1970-01-01
    • 2021-11-18
    • 1970-01-01
    • 1970-01-01
    • 2012-06-10
    • 1970-01-01
    • 1970-01-01
    • 2021-03-20
    • 1970-01-01
    相关资源
    最近更新 更多