解包选项(Swift 游乐场)

Unwrapping Optionals (Swift Playground)

关于展开可选值的简单问题。

我已经阅读并看到了像下面这样展开的多个示例

var strArray: [String]?
strArray = ["John", "Stacy", "Stephanie" ]

if let forSureNames = strArray{
   for name in forSureNames{
      print("\(name)")
   }
} else{
    print("Failed unwrapping")
}

但是,我的问题是 if let forSureNames = strArray{...

当键入类似于 C++ 的语法时(以及一些 swift 示例),添加括号

if (let forSureNames = strArray){

给出错误代码:

'()' is not convertible to 'Bool'

error: MyPlayground.playground:13:4: error: expected expression in list of expressions
if(let forSureName = strArrays){
   ^
error: MyPlayground.playground:13:4: error: expected '{' after 'if' condition
if(let forSureName = strArrays){
   ^

谁能帮忙解释一下区别?

编辑 我第一次问有关 Stack overflow 的问题,反馈很棒。由于我对轻松过渡很熟悉,因此我尝试使用与 C++ 类似的编码风格。但是,你们明确表示这是一种不正确的方法。感谢您对展开的新的技术观点。干杯!

if (let forSureNames = strArray) {

...这是在尝试使用可选绑定。可选绑定允许您安全地解包一些可选的 constant/variable,它可以是 nil。如果分配了此值,则它满足 if 具有此展开(非可选)constant/variable.

的语句

但是,它不适用于括号,因为来自括号的值必须是 Bool 类型。可选绑定不会直接 ​​return 一个 Bool 值,它只是尝试将 constant/variable 和 隐式地 return 分配给一个布尔值基于分配是否发生。

if (true) {...} // works
if (let value = optional) {...} // doesn't work

因此,您必须删除这些括号

if let forSureNames = strArray {...}

与其他语言不同,Swift 中的条件不必放在括号内,如果不需要,建议不要使用它们。

如你所知,() 可以用来包围一个表达式,它不会影响该表达式的计算,你问的是 "why can't I do the same to let forSureNames = strArray?" 对吗?

这是因为 let forSureNames = strArray 不是表达式。您错误地解析了此语句。单词 letif let 语句的一部分。

您将 if let 语句与 C 风格的 if 语句混淆了,在 if 之后总是有一个计算结果为 Bool 的表达式。 if let 那样根本行不通。它采用以下形式:

if let <identifier> = <expression> { }

其中 expression 必须评估为可选类型。因此,将 () 放在 let <identifier> = <expression> 周围没有什么意义。你可以把 () 放在 strArray 周围,因为 that 是一个表达式,但我不明白那有什么意义。

Swift 与 C++ 有很大的不同,所以你不应该对 C++ 语法在 Swift.

中不起作用感到惊讶。

Swift中有两种类型的if语句:采用表达式的类型(if foo.bar)和进行模式匹配的类型(if let foo = bar , if case .some(let foo) = bar, 等等).

因为Swift支持括号表达式,所以if foo.barif (foo.bar)作用相同:在第一种情况下,条件是foo.bar,在第二种情况下,条件是(foo.bar)。也就是说,这里的括号是条件表达式的一部分,而不是if语句的一部分。这与 C++ 形成对比,其中圆括号是 if 语句的一部分。然而,在这两种情况下,您都可以添加任意数量的括号:if (((((((((foo.bar))))))))),虽然很愚蠢,但在两种语言中表面上都是有效的。

回想一下,您可以将任意表达式括在括号中,但不能只将任何内容括在括号中。您不会在 Swift 或 C++ 中编写 (if foo.bar),因为您知道 if 不是表达式。然后,同样适用于let foo = bar。它也不是表达式,因此不能将其括在括号中。 if let foo = bar 可以,但 if (let foo = bar) 不行。

C++ 在某些情况下支持类似的语法:

if (auto foo = make_unique<int>(3)) { ... } else { ... }

此语法声明 foo 并对其进行测试(使用其 operator bool()),然后适当地分支程序。由于条件是一个声明语句,而不是一个表达式,它也不能被包裹在更多的括号中:if ((auto foo = make_unique<int>(3)))是一个编译时错误,就像Swift中的if (let foo = bar)一样。

Can anyone help explain the difference?

区别在于Swift不是C++。尽管它们在许多方面相似,但它们具有不同的语法。文法(部分)定义了语言的句法。

在 C++ 中,if 语句是语法中 the selection-statement production 的一部分:

selection-statement:

if ( condition ) statement

if ( condition ) statement else statement

switch ( condition ) statement

因此 if 语句的条件括号是 if 语句的一部分,而 不是 条件的一部分。

在Swift中,if语句是语法中the if-statement production的唯一产生式:

if-statementif condition-list code-block else-clauseopt

请注意,if 语句 的产生式中没有括号。因此,如果要有括号,它们必须是 condition-list 产生式的一部分。 Here's how condition-list is defined:

condition-list → condition | condition , condition-list

condition → expression | availability-condition | case-condition | optional-binding-condition

所以一个条件列表是一个或多个条件,用逗号分隔。如果您单击 condition 中的四个选项中的每一个,您会发现 availability-condition 必须以标记 #availability 开头,case-condition 必须以标记 case 开头,并且 optional-binding-condition 必须以标记 [=28] 开头=] 或令牌 var。 None 这三个作品可以以括号标记开头。

唯一可以以标记 ( 开始的 condition 的产生式是 expression 产生式,并且 expression production 在 token (.

之后不能有 token let