为什么速记参数名称不能在这个Swift闭包中起作用?

时间:2015-10-27 03:51:04

标签: swift closures

这是一个Swift函数,它接受两个int和一个三arg函数,并调用传入函数。

func p(x:Int, _ y:Int, _ f: (Int, Int, Int) -> ()) {
    f(x, y, 0)
}

我可以使用尾随闭包语法和简写参数名称来调用它,没问题:

> p(1, 2) {print($0 + $1 + $2)}

3

按预期工作。但是在Foundation库中,有一个名为enumerateSubstringsInRange的字符串方法,定义如下:

func enumerateSubstringsInRange(
      _ range: Range<Index>, 
      options opts: NSStringEnumerationOptions, 
      _ body: (substring: String?, 
               substringRange: Range<Index>, 
               enclosingRange: Range<Index>, 
               inout Bool) -> ())

好的,这很容易:该函数有三个参数,最后一个是四参数函数。就像我的第一个例子!或者我认为......

我可以将此函数与尾部闭包语法一起使用,但我不能使用简写参数名称!我不知道为什么。这就是我试过的:

let s = "a b c"
"a b c".enumerateSubstringsInRange(s.characters.indices, options: .ByWords) {(w,_,_,_) in print(w!)} 

a
b
c

一切都好;我只想一次打印出匹配的单词。当我通过闭包指定为“{(w,,_)in print(w!)}`时,这是有效的。但是,当我尝试使用简写参数语法编写闭包时,灾难:

> "a b c".enumerateSubstringsInRange(s.characters.indices, options: .ByWords) {print($0!)}
repl.swift:9:86: error: cannot force unwrap value of non-optional type   '(substring: String?, substringRange: Range<Index>, enclosingRange: Range<Index>, inout Bool)' (aka '(substring: Optional<String>, substringRange: Range<String.CharacterView.Index>, enclosingRange: Range<String.CharacterView.Index>, inout Bool)')

那我做错了什么?!错误消息似乎表明,闭包参数$0 args的整个元组。事实上,当我尝试这种情况时,情况确实如此!

>"a b c".enumerateSubstringsInRange(s.characters.indices, options: .ByWords) {print($0.0!)}

a 
b
c

所以我非常困惑。为什么在第一种情况下(我的函数p,参数被理解为$0$1等,但在第二种情况下,所有参数都汇总为一个元组?或者是他们?FWIW,我找到了enumerateSubstringsInRange here的签名。

1 个答案:

答案 0 :(得分:3)

这取决于参数的数量。

例如,

func test( closure: (Int,Int,Int) -> Void ){
    // do something
}

要使test按预期工作,您必须指定$2(第三个参数)。编译器将推断元组内部的值,否则它将推断元组本身。

如果未指定与参数数量匹配的$number。例如,仅指定$1,将导致编译错误。

// work as expected ( infer to int )
test{
    print($2)
}
test{
    print($1+$2)
}
test{
    print($0+$1+$2)
}

// not work ( infer to tuple )
test{
    print($0)
}

// not work ( cannot infer and compile error )
test{
    print($1)
}

有一个问题与此问题有关。 Why is the shorthand argument name $0 returning a tuple of all parameters?