Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/19.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
If statement Swift&x27;s可选绑定到类型it';谁的论点?_If Statement_Swift_Syntax_Assignment Operator_Optional - Fatal编程技术网

If statement Swift&x27;s可选绑定到类型it';谁的论点?

If statement Swift&x27;s可选绑定到类型it';谁的论点?,if-statement,swift,syntax,assignment-operator,optional,If Statement,Swift,Syntax,Assignment Operator,Optional,为什么 (因此是无效的赋值)特别是当 if let y: Int? = nil as Int?? { ... } 不一样 let y: Int? = nil (因为让y:Int?=nil是一个有效的作业)好的,我会回答,因为我的英语水平很差;-) 让我们从这个开始: let y: Int? = nil as Int?? 首先,编译器尝试使用可选包装将右值转换为T?。例如: if let lvalue:T = rvalue { ... } 然后运行时通过展开一次来查看转换后的rvalue

为什么

(因此是无效的赋值)特别是当

if let y: Int? = nil as Int?? { ... }
不一样

let y: Int? = nil

(因为
让y:Int?=nil
是一个有效的作业)

好的,我会回答,因为我的英语水平很差;-)

让我们从这个开始:

let y: Int? = nil as Int??
首先,编译器尝试使用
可选
包装将
右值
转换为
T?
。例如:

if let lvalue:T = rvalue { ... }
然后运行时通过展开一次来查看转换后的
rvalue
,无论该值是否为
nil
。如果不是
nil
,则分配并成功

如果让左值:T=rvalue{…}


另一方面,

typealias T = Int
let rvalue:Int? = 1
if let lvalue:T = rvalue { ... } // do nothing because `rvalue` is already `T?`

//---

typealias T = Int??
let rvalue:Int = 1
if let lvalue:T = rvalue { ... } // rvalue will be converted to `T?`, that is `Int???`

//---

typealias T = Int
let rvalue:Int?? = 1
if let lvalue:T = rvalue { ... } // error because `rvalue` could not be converted by wrapping with Optional
这是相似的,但不一样。编译器尝试将
rvalue
转换为
T
,而不是
T?

let lvalue:T = rvalue
然后运行时可以无条件地将
rvalue
分配给
lvalue

我想这就是区别


要观察这些编译器的工作,可以使用
swiftc-dump ast
命令

typealias T = Int??
let rvalue:Int?? = 1
let lvalue:T = rvalue // Do nothing because `rvalue` is `T`

//---

typealias T = Int??
let rvalue:Int = 1
let lvalue:T = rvalue // rvalue will be converted to `T`, that is `Int??`
$cat test.swift
让我:Int?=1.
如果让y:Int?=i{}
$xcrun swiftc-转储ast test.swift
(源文件)
(顶级代码)
(大括号)
(图案装订)
(模式类型为type='Int?)
(模式名称为type='Int?'i')
)
(在可选隐式type='Int'位置=test.swift:1:14范围=[test.swift:1:14-行:1:14]中插入\u)
(call_expr implicit type='Int'location=test.swift:1:14 range=[test.swift:1:14-行:1:14]
(构造函数_ref_call_expr implicit type='(_builtintegerlateral:Int2048)->Int'location=test.swift:1:14范围=[test.swift:1:14-行:1:14]
(declref_expr implicit type='Int.type->(_builtinteregeral:Int2048)->Int'location=test.swift:1:14 range=[test.swift:1:14-line:1:14]decl=swift.(file.Int.init(_builtinteregeral:)specialized=no)
(type_expr implicit type='Int.type'location=test.swift:1:14 range=[test.swift:1:14-line:1:14]typerepr='')
(tuple_expr implicit type='(_builtintegerliteral:Int2048)location=test.swift:1:14 range=[test.swift:1:14-line:1:14]name=_builtintegerliteral
(integer_literal_expr type='Int2048'location=test.swift:1:14 range=[test.swift:1:14-line:1:14]value=1щщщ)
)
(var_decl“i”type='Int?'access=internal let storage\u kind='storage')
(顶级代码)
(大括号)
(如果
(图案装订)
(模式类型为type='Int?)
(模式名称为type='Int?'y')
)
(将_注入_可选隐式type='Int??'位置=test.swift:2:17范围=[test.swift:2:17-行:2:17]
(declref_expr type='Int?'location=test.swift:2:17 range=[test.swift:2:17-line:2:17]decl=test.(文件)。i@test.swift:1:5=否)
(大括号)

考虑一下可选绑定的用途。它允许您获取可选值,并根据它是否为
nil
设置条件,如果它不是
nil
,则打开包含的值并将其绑定到变量。因此,它是这样的:

$ cat test.swift
let i:Int? = 1
if let y:Int? = i { }

$ xcrun swiftc -dump-ast test.swift
(source_file
  (top_level_code_decl
    (brace_stmt
      (pattern_binding_decl
        (pattern_typed type='Int?'
          (pattern_named type='Int?' 'i')
)
        (inject_into_optional implicit type='Int?' location=test.swift:1:14 range=[test.swift:1:14 - line:1:14]
          (call_expr implicit type='Int' location=test.swift:1:14 range=[test.swift:1:14 - line:1:14]
            (constructor_ref_call_expr implicit type='(_builtinIntegerLiteral: Int2048) -> Int' location=test.swift:1:14 range=[test.swift:1:14 - line:1:14]
              (declref_expr implicit type='Int.Type -> (_builtinIntegerLiteral: Int2048) -> Int' location=test.swift:1:14 range=[test.swift:1:14 - line:1:14] decl=Swift.(file).Int.init(_builtinIntegerLiteral:) specialized=no)
              (type_expr implicit type='Int.Type' location=test.swift:1:14 range=[test.swift:1:14 - line:1:14] typerepr='<<IMPLICIT>>'))
            (tuple_expr implicit type='(_builtinIntegerLiteral: Int2048)' location=test.swift:1:14 range=[test.swift:1:14 - line:1:14] names=_builtinIntegerLiteral
              (integer_literal_expr type='Int2048' location=test.swift:1:14 range=[test.swift:1:14 - line:1:14] value=1)))))
)
  (var_decl "i" type='Int?' access=internal let storage_kind='stored')
  (top_level_code_decl
    (brace_stmt
      (if_stmt
        (pattern_binding_decl
          (pattern_typed type='Int?'
            (pattern_named type='Int?' 'y')
)
          (inject_into_optional implicit type='Int??' location=test.swift:2:17 range=[test.swift:2:17 - line:2:17]
            (declref_expr type='Int?' location=test.swift:2:17 range=[test.swift:2:17 - line:2:17] decl=test.(file).i@test.swift:1:5 specialized=no)))

        (brace_stmt))))
因此,如果
optional\u expr
的类型是
T?
,那么
non\u optional\u var
的类型是
T
(当我写“non\u optional\u var”时,我并不是说它不能是可选的,而是说它的可选性比“optional\u expr”低一级。因此,如果
非可选变量
的类型为
Int?
,则
可选表达式
的类型为
Int??

顺便说一下,可选绑定语法是用于打开
optional
enum:

if let non_optional_var = optional_expr {
    ...
} else {
    ...
}

我想你已经开始转向一个更好的领域了。真正的Swift团队在那里回答问题,这样你就可以得到更明确的答案,并有一个来回的过程来了解细节。@NateCook:不知道为什么。你能解释一下吗?这似乎和这里的任何其他问题没有什么不同:我不需要o知道发生了什么,这样我就可以避免编码错误。我并不是说你不应该在这里问,只是说你可能会在开发论坛(或者在#swiftlang上,老实说)有更好的运气。看起来你更像是在探索可选绑定和可选绑定如何工作的边缘,而不是实际处理编写代码;
如果让y:Int?=nil{}
完全忽略了可选绑定的意义,所以我看不出这是您实际遇到的问题。@NateCook:我想这会揭示可选绑定的工作原理。因为它似乎是
var x:Int?=nil;如果让y:Int?=x{…}的核心
。这是打开这两个问题的钥匙。否则,所有这些都没有多大意义(对我来说)。我还认为@rintaro应该在这里解释一下它的来源。可能是重复的谢谢!所以在条件绑定中,
rvalue
总是首先包装在
Optional
中;然后才拆开一次包装,看看赋值是否有效?在(常规)赋值中,没有包装(当然)而
rvalue
只是检查一下,看看它是否可以转换成
lvalue
的类型?是的,我想可以。在我看来,你应该用
swiftc-dump ast
检查一下。你可以看到编译器何时以及如何将
inject\u插入到\u optional
s.Hmmm中。所以如果步骤真的是1:可选绑定,如果有的话(停止在
nil
上,否则求值并以可选方式换行);2:换行(再次,始终?);3:查找“内部”(==unwrap?);4:尝试分配结果,那么我理解上述内容,但我不理解
如果让y3:Int=x1?{…}
如果让y4:Int=x1{…}
,如果我们已经完成了
x1=42
。这些步骤在步骤4中带有
可选(42)
,无法分配?我没有正确的步骤吗?它们是n吗
if let non_optional_var = optional_expr {
    ...
} else {
    ...
}
switch optional_expr {
case .Some(let non_optional_var):
    ...
case .None:
    ...
}