【问题标题】:Why does use of closure shorthand-named variables has to be exhaustive in a singular return expression in Swift?为什么在 Swift 的单数返回表达式中使用闭包简写变量必须详尽无遗?
【发布时间】:2017-03-26 22:10:55
【问题描述】:

以下代码在 Swift 中是错误的。

func foo(closure: (Int, Int) -> Int) -> Int {
    return closure(1, 2)
}

print(foo(closure: {$0}))

func foo(closure: (Int, Int) -> Int) -> Int {
    return closure(1, 2)
}

print(foo(closure: {return $0}))

XCode Playground 给出的错误是Cannot convert value of type '(Int, Int)' to closure result type 'Int'

虽然下面几段代码完全没问题。

func foo(closure: (Int, Int) -> Int) -> Int {
    return closure(1, 2)
}

print(foo(closure: {$0 + $1}))

func foo(closure: (Int, Int) -> Int) -> Int {
return closure(1, 2)
}
print(foo(closure: {$1; return $0}))

func foo(closure: (Int, Int) -> Int) -> Int {
    return closure(1, 2)
}

print(foo(closure: {a, b in a}))

似乎在闭包的参数由速记参数名称引用的情况下,如果闭包的主体仅由返回表达式组成,则必须彻底使用它们。为什么?

【问题讨论】:

标签: swift swift3 closures


【解决方案1】:

如果您只使用$0,则假定闭包参数是一个元组而不是多个变量$0$1 等。因此您应该能够通过提取该元组的第一个值来解决此问题:

print(foo(closure: {$0.0}))

【讨论】:

    【解决方案2】:

    您的“为什么”就像问“为什么美式足球场有 100 码长?”因为那是规矩。接受参数的匿名函数体必须明确确认所有参数。它可以通过以下三种方式中的任何一种来做到这一点:

    • 使用$0$1、...表示法来表示它们。

    • in 行中使用参数名称表示它们。

    • in 行中使用_ 明确丢弃它们。

    所以,让我们举一个比你的简单得多的例子:

    func f(_ ff:(Int)->(Void)) {} 
    

    如您所见,函数f接受一个参数,也就是一个接受一个参数的函数。

    那么,让我们尝试将一些匿名函数交给f

    这是合法的,因为我们在 in 行中命名参数:

    f {
        myParam in
    }
    

    这是合法的,因为我们接受使用$0 表示法的参数:

    f {
        $0
    }
    

    这是合法的,因为我们在in 行中使用_ 明确丢弃了参数:

    f {
        _ in
    }
    

    但这不合法:

    f {
        1 // error: contextual type for closure argument list expects 1 argument, 
        // which cannot be implicitly ignored
    }
    

    【讨论】:

    • 问问题的原因难道不是隐藏规则,而不是规则吗?我相信我们都希望 Swift 的设计是有道理的 ;-)
    • @CRD 就像 Swift 的许多规则一样,这一切都是为了让您明确承认自己知道自己在做什么。考虑override;它什么也没增加(因为 Objective-C 不使用它),所以如果你覆盖一个继承的成员,“为什么”需要它?为了让你明确。
    • 我认为您误解了我的评论,可能还不够清楚。实际上,我认为这与 Swift 中类型推断的工作方式有关(参见@Palle 的回答),这就是“为什么”——而不是因为它是规则。类型推断不必以这种方式工作,一种不同的方法可以支持 OP 的预期(但可能不是 Swift 所做的其他事情——这都是关于选择的)。 OP 提出了一个合理的问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-12-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多