Почему не сортирует или космический корабль (летающая тарелка) оператор () работа над логическими значениями в Ruby?


В " Можно ли отсортировать список объектов в зависимости от того, отвечает ли отдельный объект на метод?", я обнаружил, что летающая тарелка не работает на булевых числах.

Рассмотрим:

Ruby 1.8.7:

[true, false].sort # => undefined method `<=>' for true:TrueClass (NoMethodError)
true <=> false     # => undefined method `<=>' for true:TrueClass (NoMethodError)

Ruby 1.9.3:

[true, false].sort # => comparison of TrueClass with false failed (ArgumentError)
true <=> false     # => nil
true <=> true      # => 0
false <=> true     # => nil

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

Это ошибка в sort?

3 11

3 ответа:

Логические значения не имеют естественного порядка.

Вероятно, разработчики Ruby language designer(s) посчитали, что изобретение порядка для булевых символов будет сюрпризом для разработчиков,поэтому они намеренно оставили операторы сравнения.

Так называемая летающая тарелка требует всех операторов сравнения.(<, >, ==) работать (не технически, хотя, конечно, теоретически). true и false не меньше и не больше друг друга. То же самое будет справедливо и для nil. Для практического решения проблемы вы можете "привести" к целым числам (0 для false, 1 для true). Что-то вроде:

[true, false, true].sort_by{|e| e ? 1 : 0}

Булевы не имеют естественного порядка. В отличие от C, false не меньше, чем true, это просто эквивалентные и равнозначные состояния. Однако можно настроить сортировку любым удобным вам способом, используя блок, например:

ary = [true, false, false, true]
ary.sort {|a,b|  a == b ? 0 : a ? 1 : -1 }

# => [false, false, true true]

Изменение порядка также тривиально:

ary.sort {|a,b|  a == b ? 0 : a ? -1 : 1 }

# => [true true, false, false]