Почему необязательная привязка Swift в некоторых случаях завершается успешно с нулевым значением?

В документации по языку Swift от Apple говорится, что необязательное связывание (также известное как if let) "проверит значение внутри необязательного" и "извлечет это значение в" переменную или константу). Но это не соответствует тому, что я вижу. Например

var x: Int? = nil

if let y1: Int? = x {
    println("y1 = \(y1)") // This is printed, suggesting that x is not checked "inside", but left as Optional(nil) (!= nil)
}

if let y2: Int? = x? {
    println("y2 = \(y2)")
}

if let y3: Int = x? {
    println("y3 = \(y3)")
}

if let y4: Int = x {
    println("y4 = \(y4)")
}

if let y5 = x? {
    println("y5 = \(y5)")
}

if let y6 = x {
    println("y6 = \(y6)")
}

приводит к (только)

"y1 = nil"

предполагая, что проверка «внутри» x не выполняется в случае y1 (и что x остается как обернутый nil, который не равен развернутому nil). Случай y2, кажется, подтверждает это, вызывая "проверку внутри" (или это просто необязательная цепочка "берет верх"); но в этой истории должно быть что-то еще, поскольку случаи y4 и y6 также не печатаются и, таким образом, ведут себя так, как будто происходит «внутренняя проверка».

Я подозреваю, что есть некоторое понимание, которое можно получить, попробовав

"x = 42"

что приводит к

"y1 = Optional(42)"
"y2 = Optional(42)"
"y3 = 42"
"y4 = 42"
"y5 = 42"
"y6 = 42"

но если там есть трое, то это для меня пропало.

Похоже, что (1) «необязательный» в правой части выражения действительно «проверяется внутри», если запрашивается явная проверка (с ?); но в противном случае (2) левая часть выражения влияет на то, насколько глубоко «внутри» выполняется проверка (достаточно, чтобы сделать действительное присваивание).

Как необязательное связывание работает в каждом из этих случаев? В частности, когда x == nil почему печатается y1, а учитывая это, почему не печатаются y4 и y6 (или не генерируются ошибки присваивания)?


person orome    schedule 26.10.2014    source источник


Ответы (2)


Я интерпретирую это по-другому:

var x: Int? = 1

if let y1: Int = x {
    println("y1 = \(y1)") 
}

//prints y = 1, the optional was checked, contains a value and passes it

var x: Int? = nil

if let y1: Int = x {
    println("y1 = \(y1)") 
}

//does not execute because x does not contain value that can be passed to a non optional y

var x: Int? = nil

if let y1: Int? = x {
    println("y1 = \(y1)")
}
// y = nil, since y is optional and can hold a value of x which is nil, then it passes nil

Необязательная привязка предназначена для проверки того, содержит ли необязательный параметр значение для передачи необязательному параметру.

person Steve Rosenberg    schedule 26.10.2014
comment
Вот как это выглядит: правая часть сначала проверяется на необязательную цепочку (именно там заканчиваются первые случаи y2, y3 и y5). Затем, если это не nil, то все продолжается, если можно сделать допустимое назначение. Это так просто? - person orome; 26.10.2014
comment
да, если где-то в цепочке оно равно нулю, привязка не будет выполнена. Если вам нужно знать, где произошел сбой привязки, здесь есть хорошее обсуждение: title="как узнать, где нарушается необязательная цепочка"> stackoverflow.com/questions/26524246/ - person Steve Rosenberg; 26.10.2014
comment
Итак: в случаях y2, y3 и y5 необязательная цепочка попадает в nil и все заканчивается. В случаях y4 и y6 выполняется проверка внутри x, и nil находится (и не может быть присвоено необязательным), так что все заканчивается. Но я все еще не понимаю, что именно происходит с y1: похоже, здесь не происходит никакой проверки внутри. Если бы это было так, что-то пошло бы не так (например, if let y1: Int? = nil { ...} терпит неудачу). Похоже, что проверка внутри происходит по мере необходимости, чтобы задание заработало. - person orome; 26.10.2014
comment
Я думаю, что есть путаница вокруг синтаксиса x? когда x изначально является необязательным. Я бы никогда не подумал попробовать такой синтаксис. Я интерпретирую это как {nil} или что-то вроде nil. Который в объявлениях присваивания, по-видимому, не обрабатывается так же, как сам nil, даже если он печатается как nil на игровой площадке. В любом случае, умную проблему вы поставили. - person Steve Rosenberg; 26.10.2014
comment
Я думаю, вы великодушны: я не уверен, что есть путаница; это может быть просто я, который запутался. Это, конечно, надуманный пример, но я предположил, что это точно так же, как и любое другое необязательное выражение цепочки, x?.something, за исключением того, что что-то является тождеством, то есть оно ничего не делает, поэтому, если то, что находится внутри x, не является nil, выражение перепаковывается как обычно. (поскольку выражение может быть nil и должно быть необязательным). - person orome; 26.10.2014
comment
Если это так, то я понимаю, что происходит на всех правых сторонах; и что меня здесь смущает, так это то, что просмотр внутри правой стороны (после любой необязательной цепочки или других действий с ? там) происходит только, если необходимо выполнить допустимое присваивание (например, от необязательного к необязательный). Следовательно, в случае y1 нет возможности заглянуть внутрь, потому что работает назначение Int? и Int?; в то время как x2 споткнулся на необязательной цепочке (он встретил nil). - person orome; 26.10.2014
comment
Что меня смутило, так это документация, из-за которой кажется, что всегда происходит взгляд внутрь. То есть правая сторона всегда развернута, а это явно не так, иначе y1 вел бы себя как if let y1: Int? = nil { ...} (если только не происходит что-то еще). - person orome; 26.10.2014

Вы присвоили необязательному Int необязательному Int. Задание удалось. Это всегда будет успешным, независимо от того, содержит ли необязательный Int Int или нет.

person gnasher729    schedule 26.10.2014
comment
Таким образом, в этом случае (y1) проверки внутри не происходит. Такие проверки, по-видимому, на самом деле происходят только тогда, когда это необходимо для выполнения задания (случаи y4 и y6, как показано, когда x не является nil). Верно? - person orome; 26.10.2014
comment
Суть здесь (для меня) в том, почему let y1: Int? = nil { ...} ведет себя иначе, чем let y1: Int? = x { ...}, где x равно nil. (См. обсуждение другого ответа). - person orome; 26.10.2014