Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Swift中保持关闭内的局部状态_Swift_Closures - Fatal编程技术网

在Swift中保持关闭内的局部状态

在Swift中保持关闭内的局部状态,swift,closures,Swift,Closures,有没有办法在闭包中声明一个变量,并让它在枚举调用之间保持其状态。具体来说,我想在一个数组上编写一个.filter闭包,该数组返回一个没有重复的数组版本。像这样的 let withDupes = ["C", "D", "A", "J", "J", "D", "M", "Z", "A"] let noDupes = withDupes.filter { static var seenLetters: [Character] = [ ] //would like to use st

有没有办法在闭包中声明一个变量,并让它在枚举调用之间保持其状态。具体来说,我想在一个数组上编写一个.filter闭包,该数组返回一个没有重复的数组版本。像这样的

let withDupes = ["C", "D", "A", "J", "J", "D", "M", "Z", "A"]  

let noDupes = withDupes.filter {  
    static var seenLetters: [Character] = [ ]  //would like to use static like in C  
    if !contains(seenLetters, $0) {  
        seenLetters.append($0)  
                return true  
            }  
            else {  
                return false  
            }  
    }  
//理想情况下,noDupes现在应该是[“C”、“D”、“A”、“J”、“M”、“Z”]


当我尝试以这种方式使用static时,Swift会报告一个错误。如果我全局声明seenLetters,.filter可以正常工作。是否有我丢失或误用的语言功能?

正如您所发现的,Swift不允许您直接在函数或闭包中定义
静态变量。然而,还有另一种方法可以完成你想做的事情。如果将重复数据消除代码移到其自己的函数中,则可以创建一个作用域为该函数的
seenLetters
数组
,并在
过滤器
调用中使用该数组。像这样:

let withDupes = ["C", "D", "A", "J", "J", "D", "M", "Z", "A"]

func deduplicate(arr: [String]) -> [String] {
    var seenLetters = [String]()
    return arr.filter {
        if !contains(seenLetters, $0) {
            seenLetters.append($0)
            return true
        }
        else {
            return false
        }
    }
}

let noDupes = deduplicate(withDupes)
请注意,由于您可以在其他函数中嵌入函数,因此这很好:

func someFunction() {
    let withDupes = ["C", "D", "A", "J", "J", "D", "M", "Z", "A"]

    func deduplicate(arr: [String]) -> [String] {
        /* ... */
    }

    let noDupes = deduplicate(withDupes)
}
如果出于某种原因不想创建一个单独的函数来实现这一点,那么实际上也可以使用闭包来实现。诀窍是将闭包封装在另一个闭包中,该闭包定义一个局部
seenLetters
变量并返回原始闭包。这样,
seenLetters
的作用域就是外部闭包,您的内部闭包可以按照您的意愿使用它

let noDupes = withDupes.filter({
    var seenLetters = [String]()
    return {
        if !contains(seenLetters, $0) {
            seenLetters.append($0)
            return true
        }
        else {
            return false
        }
    }
}()) // Immediately calling the outer closure so that the inner one is returned to filter
有几件事需要注意。。。首先,您需要将外部闭包的返回值传递给
filter
函数,只需立即调用它即可。第二,您不能将其用作尾随闭包,因此必须在
过滤器
调用中将其包装在
()
s中。第三,这与使用嵌入式函数基本相同,只是形式更紧凑