В Ruby, почему делает равенство с нолем (“Date.new == ноль”) возвращают ноль?

При записи некоторого rspec сегодня, я столкнулся с некоторым неожиданным поведением со сравнением Даты (и Время) экземпляры к нолю. Вот демонстрационный рубин сырых данных использования (никакие направляющие или другие библиотеки):

user@MacBook-Work ~ $ ruby -v
ruby 1.8.7 (2008-08-11 patchlevel 72) [universal-darwin10.0]
user@MacBook-Work ~ $ irb
>> 1 == nil
=> false
>> "string" == nil
=> false
>> :sym == nil
=> false
>> false == nil
=> false
>> [] == nil
=> false
>> {} == nil
=> false
>> Proc.new {} == nil
=> false

Пока неплохо, правильно?

>> Date.new == nil
=> nil
>> Time.new == nil
=> nil

Дата действительно реализует свой собственный ===, который хорошо работает:

>> Date.new === nil
=> false

Там какое-либо объяснение относительно того, почему это происходит или почему это - желаемое поведение? ==, кажется, реализован от Сопоставимого. ==, однако документация относительно этого не делает, учитывая никакой признак, что она когда-либо возвращала бы ноль. Что проектное решение к этому?

Обновление! Дело обстоит не так в 1.9.2:

$ irb
ruby-1.9.2-p136 :001 > require 'date'
 => true 
ruby-1.9.2-p136 :002 > Date.new == nil
 => false 
ruby-1.9.2-p136 :003 > Time.new == nil
 => false 
17
задан Gabe Martin-Dempesy 28 July 2011 в 01:17
поделиться

4 ответа

Я проверил источник и вот что выяснил:

Все операторы сравнения, определенные Comparable, используют функцию rb_cmpint вместе с <=> . rb_cmpint вызывает исключение, когда один из операндов равен нулю.

Таким образом, операторы Comparable вызывают исключение, если rhs не сопоставимо с lhs. Т.е. 5 <2 ложно, но 5 <"la" вызывает исключение. Они делают это, чтобы различать случаи, когда < неверно, потому что правая сторона меньше, и случаи, когда она неверна, потому что правая сторона несопоставима. Или другими словами: когда x ложно, это означает, что x> = y истинно. Поэтому в случаях, когда это не так, он генерирует исключение.

== создание исключения было бы плохим, потому что == обычно не требует (и не должен) требовать, чтобы его операнды были сопоставимы. Однако == использует тот же метод, что и другие операнды, что вызывает исключение. Таким образом, вся функция просто заключена в rb_rescue . И это возвращает nil , если возникает исключение.

Обратите внимание, что это относится только к рубину 1.8.Это было исправлено в версии 1.9, и теперь == никогда не возвращает nil (кроме, конечно, если вы определяете свой собственный == , который это делает).

12
ответ дан 30 November 2019 в 13:27
поделиться

Класс Date включает метод Comparable # == , но этот метод вызывает метод <=> приемника. В данном случае это Date # <=> , который ожидает другой объект Date. Когда он получает nil , он возвращает nil . Такое поведение определенно кажется непоследовательным, и я не знаю его причин.

4
ответ дан 30 November 2019 в 13:27
поделиться

Если вы зависите от этого кода, вы всегда можете использовать .nil? метод, на который реагирует любой объект Ruby.

>> Date.new.nil?
=> false
7
ответ дан 30 November 2019 в 13:27
поделиться

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

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

0
ответ дан 30 November 2019 в 13:27
поделиться
Другие вопросы по тегам:

Похожие вопросы: