2014-10-03 2 views
22

Это правильный код в Swift:Swift nil имеет числовое значение?

println(nil < 1) 

И выход будет верно, также

println(nil > 1) 

будет ложным (число 1 произвольно, вы можете сделать то же самое для -1 и вероятно, что-то еще). Причина, о которой я прошу, заключается в том, что я видел код, который пытался сравнить "some_string".toInt() с числовым значением и скомпилировал его, что кажется неправильным, учитывая, что toInt() возвращает Int?.

Вопрос в том, должен ли это быть допустимым синтаксисом в Swift? Если да, то каково числовое значение nil?


Swift 3,0 Обновление:

Похоже Swift Evolution решать эту проблему removing the optional comparison operators. Это уже не проблема в Swift 3.0, поскольку она не компилируется.

+2

это выглядит как ошибка для меня. –

+0

'Int.min as Int? > nil' '$ R14: Bool = true', возможно, это позволит вам сравнить две ошибки' Int? 'и 'Int.min> nil' дать компиляцию –

+0

@BryanChen Это, безусловно, интересно. Я бы определенно сказал об ошибке в этом контексте, но мне очень хотелось бы знать, как он приходит к такому выводу. –

ответ

17

Я считаю, что происходит то, что буквально 1 неявно приписывает тип Int? для сравнения с nil. Для тех, кто не привык к Свифт, я объясню немного дальше. У Swift есть концепция под названием «optionals», которая может иметь значение или быть nil. (Для тех, кто знаком с Haskell, это в основном монада Maybe.) Неправильно назначать nil переменной, которая явно не указана как необязательная, поэтому let i: Int = nil будет отклонена компилятором. Это позволяет использовать несколько преимуществ, которые выходят за рамки этого ответа, и это довольно умный способ сделать это.

Что здесь происходит, однако, является то, что буквальное 1 является допустимым значением нескольких типов: Int, Int32, Int64, UInt32, UInt64 и т.д., и т.д., и т.д. И это также действительное значение факультативные версии этих типов: Int?, Int32? и т.д.

Так что, когда Swift компилятор видит сравнение между буквальным значением и nil, он пытается найти тип, что оба эти значения будут справедливы для. 1 является допустимым значением типа Int?, а nil также является допустимым значением типа Int?, поэтому применяется оператор сравнения с типом подписи (Int?, Int?) -> Bool. (Это оператор сравнения, который принимает два значения Int? и возвращает Bool). Правила этого оператора говорят, что значения nil сортируются ниже, чем что-либо еще, даже Int.min, и поэтому вы получаете результат, увиденный в вопросе OP.

+1

Кстати, это было невозможно в Haskell (как я понимаю), потому что монада «Maybe» определяется как имеющая два возможных значения: либо «Nothing», либо «Just x» (где 'x' может быть любого тип). И так как 'x' никогда не может быть неявно продвигаться до« Just x », компилятор Haskell будет иметь заданный оператор сравнения, который сравнивает типы« Maybe Int »и« Maybe Int », запрещает любое сравнение между« 1 »и« Nothing » , потому что первый имеет тип 'Int', и нет оператора для сравнения' Int' и 'Maybe Int'. (Но сравнение «Just 1» и «Nothing» было бы правильным: оба типа «Maybe Int»). – rmunn

+0

Исправление к скобке в моем предыдущем комментарии: 'Nothing' имеет значение' Maybe x', где 'x' может быть любым типом. Но это соответствует типу 'Maybe Int', поэтому сравнение будет действительным. – rmunn

+7

Одной из сигнатур оператора '<' является: 'func << T: _Comparable> (lhs: T ?, rhs: T?) -> Bool'; Я верю, что это откуда. Написание быстрой тестовой функции: 'func test (lhs: T ?, rhs: T?)' И вызов 'test (nil, 1)' работает. Вызов 'println (_stdlib_getDemangledTypeName (rhs))' внутри этой функции печатает 'Swift.Optional'; вызов 'println (_stdlib_getDemangledTypeName (rhs!))' печатает 'Swift.Int'. Итак, 'rhs', который был передан как« 1 »в вызове, является« Int? ». –

Смежные вопросы