【问题标题】:Unwrapping Optionals (Swift Playground)解包选项(Swift Playground)
【发布时间】:2019-01-14 21:20:21
【问题描述】:

关于解包选项的简单问题。

我已经阅读并看到了多个展开示例,如下所示

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){
   ^

谁能帮忙解释一下区别?

编辑 我第一次问关于堆栈溢出的问题,反馈很棒。由于我对轻松转换的熟悉,我试图使用与 C++ 类似的编码风格。但是,你们明确表示这是一种不正确的方法。感谢您对展开的全新技术视角。干杯!

【问题讨论】:

  • 赋值不等于 swift 中的布尔表达式。 let forSureNames = strArray 不会评估为真或假

标签: swift conditional-statements optional forced-unwrapping


【解决方案1】:

如您所知,() 可用于包围表达式,并且不会影响对该表达式的评估,而您在问“为什么我不能对 let forSureNames = strArray 做同样的事情?”对吧?

这是因为let forSureNames = strArray 不是表达式。您正在解析此语句错误。 let 这个词是 if let 语句的一部分。

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

if let <identifier> = <expression> { }

其中expression 必须计算为可选类型。所以把() 放在let &lt;identifier&gt; = &lt;expression&gt; 周围没有什么意义。您可以将 () 放在 strArray 周围,因为 that 是一个表达式,但我不明白这一点。

【讨论】:

    【解决方案2】:
    if (let forSureNames = strArray) {
    

    ...这是尝试使用可选绑定。可选绑定允许您安全地解开一些可选的常量/变量,可以是nil。如果分配了这个值,它会满足 if 声明与这个展开的(非可选的)常量/变量。

    但是,它不适用于括号,因为来自括号的值必须是 Bool 类型。可选绑定不直接返回 Bool 值,它只是尝试分配常量/变量,隐式根据分配是否发生返回布尔值。

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

    所以,你必须删除这些括号

    if let forSureNames = strArray {...}
    

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

    【讨论】:

      【解决方案3】:

      Swift 与 C++ 有很大不同,因此 C++ 语法在 Swift 中不起作用,您不必感到惊讶。

      在 Swift 中有两种类型的 if 语句:接受表达式的类型 (if foo.bar),以及进行模式匹配的类型(if let foo = barif case .some(let foo) = bar 等)。

      由于 Swift 支持带括号的表达式,if foo.bar 的工作方式与if (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&lt;int&gt;(3))) 是编译时错误,就像 Swift 中的if (let foo = bar)

      【讨论】:

        【解决方案4】:

        谁能帮忙解释一下区别?

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

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

        选择声明:

        if(条件)声明

        if ( 条件 ) 声明 else 声明

        switch(条件)声明

        所以if 语句的条件周围的括号是if 语句的一部分,而不是条件的一部分。

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

        if-statementif 条件列表代码块 else-clauseopt

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

        条件列表 → 条件 |条件,条件列表

        条件 → 表达式 |可用性条件 |案例条件 |可选绑定条件

        所以一个条件列表是一个或多个条件,用逗号分隔。如果您单击 condition 中的四个选项中的每一个,您会发现 availability-condition 必须以标记 #availability 开头,case-condition 必须以标记 case 开头,optional-binding-condition 必须以标记 let 或标记 var 开头。这三个产生式都不能以括号标记开头。

        condition 的唯一产生式可以以标记 ( 开头是 expression 产生式,而 expression 产生式不能有令牌let 在令牌( 之后。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-11-24
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多