Я столкнулся с некоторым странным поведением на языке Swift при работе в REPL (= Read-Eval-Print-Loop), где, как представляется, существуют два разных типа значений nil
с различным поведением во время выполнения
Для этого я определяю функцию g
:
func g(x:String!) {
println("start!");
println((x == "foo") ? "foo" : "not");
}
Затем я определяю две переменные:
var x:String
var y:String!
Когда я вызываю g(x)
, он работает как Objective-C:
start!
not
Когда я вызываю g(y)
, я получил сообщение об ошибке:
start!
fatal error: Can't unwrap Optional.None
Execution interrupted. Enter Swift code to recover and continue.
Enter LLDB commands to investigate (type :help for assistance.)
Обратите внимание, что эта ошибка попадает во время выполнения! Функция уже запущена. Вы можете видеть это из-за "начала!" строка на выходе.
Кажется, что в первом случае функция получает значение nil вместе с запиской "это не значение nil". Во втором случае он, кажется, получает нуль, с прикрепленной запиской "это значение равно нулю, пожалуйста, кричите и не просто используйте его".
Почему я не получил ошибку в первом случае и ошибку во втором случае? Не должно быть поведения g (x) и g (y) одного и того же?
Является ли это ожидаемым поведением? Я что-то упускаю? Это ошибка в Swift? Ошибка в спецификации? Или ошибка в реализации? Или просто ошибка в REPL?. Нельзя ли получить доступ к неинициализированным переменным?
Весь протокол сеанса, для справки...
$ /Applications/Xcode6-Beta.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/swift
Welcome to Swift! Type :help for assistance.
1> func g(x:String!) {println("start!"); println((x=="foo") ? "foo" : "not");}
2> var x:String
x: String = {
core = {
_baseAddress = Builtin.RawPointer = 0x0000000000000000
_countAndFlags = 0
_owner = None
}
}
3> var y:String!
y: String! = nil
4> g(x)
start!
not
5> g(y)
start!
fatal error: Can't unwrap Optional.None
Execution interrupted. Enter Swift code to recover and continue.
Enter LLDB commands to investigate (type :help for assistance.)
6>
Чтобы воспроизвести весь сеанс, просто введите следующий код в терминал:
/Applications/Xcode6-Beta.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/swift
func g(x:String!) {println("start!"); println((x=="foo") ? "foo" : "not");}
var x:String
var y:String!
g(x)
g(y)
(функция написана в одной строке, потому что функция копирования и вставки повреждена в REPL, по крайней мере, на моей машине. Однако это написано в одной строке... Это еще одна история...)
Обновление в марте 2015 г. Apple, похоже, исправила эту проблему. Уже невозможно объявить нормальную переменную без начального значения:
2> var x:String
repl.swift:2:1: error: variables currently must have an initial value when entered at the top level of the REPL
var x:String
^