Преобразование необязательных многозначных выражений в логические

#swift

#swift

Вопрос:

Это кажется очень простым. Заранее приношу свои извинения. Но рассмотрим следующие четыре варианта на ту же тему:

 var q : String? = nil

if let z : String? = q {
    println("q is non-nil")
} else {
    println("q is nil")
}

var zz : String? = nil
if (zz) {
    println("zz is not nil")
} else {
    println("zz is nil")
}

if let z : String? = nil {
    println("nil is non-nil")
} else {
    println("nil is nil")
}

/*
if (nil) {
    println("nil is non-nil")
} else {
    println("nil is nil")
}
*/
  

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

 q is nil
zz is nil
nil is non-nil
  

Если я раскомментирую окончательную форму, я получу…

 Playground execution failed: error: <REPL>:57:5: error: type 'NilType' does not conform to protocol 'LogicValue'
if (nil) {
  

Каковы правила, которые объясняют, когда необязательное выражение может обрабатываться как логическое, с nil как false и {Some whatever} как true ? Почему третий оператор if выводит «nil не nil», когда он кажется семантически идентичным другим? Почему значение nil является приемлемым / преобразуемым в LogicValue в операторе if при привязке к переменной или в выражении let, но не при представлении в виде литерала?

Комментарии:

1. Третья if печать nil is non-nil очень похожа на ошибку в компиляторе. Вы сообщили об этом в Apple?

2. (нет … я подумал, что, должно быть, что-то упускаю. я впервые играю со swift; когда сомневаюсь, я предполагаю, что ошибаюсь.)

3. Как правило, большую часть времени это очень разумное предположение. Бета-тестирование является одним заметным исключением из этого правила 😉

4. Существует ли какая-либо документация о том, что if let z : String? = q предполагается делать, в отличие if let z = q от того, что хорошо документировано как возвращающее значение true и разворачивающее q в z, если q не равно нулю?

5. Что касается if nil … для оператора if требуется логическое значение. nil не является логическим значением

Ответ №1:

Результат третьего случая имеет смысл. «If let» проверяет, выполнено ли назначение успешно. Обычный шаблон:

 var optional : String?
if let nonOptional : String = optional {
    // the optional could successfully be converted to a non-optional
}
  

Вы просто пытаетесь присвоить nil необязательному, что действительно возможно и допустимо. Следовательно, «пусть, если» возвращает true.

Также часто то же самое делается с назначениями с понижением

 var any : AnyObject = "Hello"
if let string = any as? String {
     // Downcast to String was successful
}
  

Наконец, это необязательный тип, который соответствует тому, чтобы быть a LogicValue , позволяя использовать его в if инструкции. Дело НЕ в том, что необязательный возвращает nil и nil проверяется. nil автономный режим не может использоваться в операторе if, поскольку он не реализует LogicValue протокол, и для этого нет причин.

Комментарии:

1. Спасибо. но разве nil не должен соответствовать самому необязательному типу, так что не нужно ли тогда реализовать протокол LogicValue, если Optional соответствует для соответствия? (еще раз извините, если я упускаю что-то очень простое.)

2. @SteveWaldman nil не обязательно должен соответствовать необязательному, необязательному просто нужно определить оператор присваивания с его помощью

Ответ №2:

Ваш Optional Binding синтаксис неверен.

это должно быть if let z = q {}

Если необходимо добавить тип, он должен быть: if let z:String = q

Если вы сделаете это,

 if let z : String = nil {
    println("nil is non-nil")
} else {
    println("nil is nil")
}
  

Это ведет себя правильно и печатается nil is nil .

В последнем случае выражение должно быть a bool . Причина if q компиляции в том, что она проверяет nil для вас и все равно возвращает логическое значение.