简体   繁体   English

为什么这个闭包代码在不使用捕获列表时会抛出错误?

[英]Why does this closure code throw an error when not using a capture list?

func biggerOne(_ a : Int, _ b : Int) -> Int? {
    if a == b {
        return nil
    } else if a > b {
        return a
    } else {
        return b
    }
}

var someClosure : (Int, Int) -> Int? = biggerOne(_:_:)

// Not working
someClosure = { (left : Int, right : Int) in
    someClosure(left , right)
}
print(someClosure(2,3)!)

// Working
someClosure = { [someClosure] (left : Int, right : Int) in
    someClosure(left , right)
}
print(someClosure(2,3)!)

I knew that closure uses capture list to store values on creation so can solve the problem but why is the code above not working?我知道闭包使用捕获列表来存储创建时的值,因此可以解决问题,但为什么上面的代码不起作用?

If you have any ideas, I would appreciate your help.如果您有任何想法,我将不胜感激您的帮助。

There are circular references, someClosure is calling itself.有循环引用, someClosure在调用自己。

Try eliminating the circular references:尝试消除循环引用:

        // Now it works
        let firstClosure = { (left : Int, right : Int) in
            someClosure(left , right)
        }
        print(firstClosure(2,3)!)
        
        // Working
        let secondClosure = { [someClosure] (left : Int, right : Int) in
            someClosure(left , right)
        }
        print(secondClosure(2,3)!)

Without capturing, someClosure here is simply calling itself, and then causing a stack overflow:没有捕获,这里的someClosure只是简单地调用自己,然后导致堆栈溢出:

someClosure = { (left : Int, right : Int) in
   someClosure(left , right) // this call refers to the new value of "someClosure"
}

(I'm not sure if the fact that this passes compilation is intentional.) (我不确定这个通过编译的事实是否是故意的。)

This is just like as if you have defined a named function like:这就像您定义了一个名为 function 的名称一样:

func someClosure(left: Int, right: Int): Int? {
    someClosure(left: left, right: right)
}

On the other hand, the capture list captures the old value of someClosure , so " someClosure " inside the closure body refers to the captured value (ie the old value), and there is no infinite recursion.另一方面,捕获列表捕获了someClosure的旧值,所以闭包体内的“ someClosure ”指的是捕获的值(即旧值),不存在无限递归。 You can think of this as:您可以将其视为:

let captured = someClosure
someClosure = { (left : Int, right : Int) in
    captured(left , right)
}

Using lldb yourExecutable and the thread backtrace command, you can see the many duplicated stack frames that are caused by the recursion.使用lldb yourExecutablethread backtrace命令,您可以看到递归导致的许多重复堆栈帧。

(lldb) thread backtrace 
* thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=2, address=0x7ff7bf6ffff8)
  * frame #0: 0x00007ff822e4fa99 libswiftCore.dylib`swift_beginAccess + 41
    frame #1: 0x0000000100003d87 yourExecutable`$s14yourExecutableSiSgSi_SitcfU_ + 71
    frame #2: 0x0000000100003dbc yourExecutable`$s14yourExecutableSiSgSi_SitcfU_ + 124
    frame #3: 0x0000000100003dbc yourExecutable`$s14yourExecutableSiSgSi_SitcfU_ + 124
    frame #4: 0x0000000100003dbc yourExecutable`$s14yourExecutableSiSgSi_SitcfU_ + 124
    ...
    frame #65515: 0x0000000100003dbc yourExecutable`$s14yourExecutableSiSgSi_SitcfU_ + 124
    frame #65516: 0x0000000100003dbc yourExecutable`$s14yourExecutableSiSgSi_SitcfU_ + 124
    frame #65517: 0x0000000100003baa yourExecutable`main + 218
    frame #65518: 0x00000001000154fe dyld`start + 462

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 为什么AudioServicesCreateSystemSoundID在内部抛出异常但返回0作为错误代码? - Why does AudioServicesCreateSystemSoundID throw an exception internally but return 0 as an error code? 当我将.repeatsForever() 添加到 animation 时,为什么 Xcode 会引发错误? - Why does Xcode throw an error when I add .repeatsForever() to an animation? Swift 构建错误:闭包捕获列表中的预期名称 - Swift build error: Expected name of in closure capture list 闭包如何捕获值? - How does the closure capture values? 为什么Fastlane会引发异常“代码签名错误:找不到代码签名身份”? - Why does Fastlane throw exception “Code Sign error: No code signing identities found”? 使用Swift闭包捕获变量 - Using a Swift closure to capture a variable 当视图控制器超过5个时,为什么设置选项卡栏控制器的selectedViewController> = 4会引发错误? - Why does setting tab bar controller's selectedViewController >= 4 throw error when there are more than 5 view controllers? 从关闭中抛出错误的正确方法? - Proper way to throw error from my closure? 什么时候应该在闭包中使用捕获列表,什么时候应该使用弱无主vs.无主? - When should i use capture list in closure, and when to use weak vs. unowned? Swift Closure为什么调用函数返回错误? - Swift Closure why does calling function return error?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM