Почему Ruby имеет TrueClass и FalseClass вместо одного логического класса?



Я работал над сериализацией значений, когда узнал об этом. У Руби есть TrueClass класс, а FalseClass класс, но у него нет Boolean класса. Я хотел бы знать, почему это.



Я вижу некоторые преимущества в использовании Boolean; например, разбор строк может быть централизован на нем.



разработчики Ruby умнее меня, поэтому должно быть много веских причин, которые я просто не вижу. Но сейчас мне кажется, что у меня есть OneClass и TwoClass вместо Fixnum.

525   8  

8 ответов:

цель класса состоит в том, чтобы сгруппировать подобные объекты или объекты с подобным поведением вместе. 1 и 2 очень похожи, поэтому для них имеет смысл быть в одном классе. true и и не похожие. На самом деле, их

похоже, что сам МАЦ ответил на этот вопрос на A список рассылки в 2004 году.

короткая версия его ответа:"сейчас он работает нормально, добавление Булева не дает никакого преимущества".

лично я не согласен с этим; вышеупомянутый "обработка строк" является одним из примеров. Другой заключается в том, что когда вы применяете различную обработку к переменной в зависимости от ее типа (т. е. парсер yml), имеющий "логический" класс удобен - он удаляет одно "если". Это тоже выглядит более корректно, но это личное мнение.

со ссылкой на МАЦ рубиновый форум (2013):

...Там нет ничего истинного и ложного обычно разделяют, таким образом, нет логического класса. Кроме того, в Ruby все ведет себя как логическое значение....

true и false могут управляться Булевым классом, который содержит несколько значений, но тогда объект класса должен иметь внутренние значения и поэтому должен быть удален при каждом использовании.

вместо этого Ruby обрабатывает true и false как длинные значения (0 и 1), каждое из которых соответствует типу класса объектов (FalseClass и TrueClass). Используя два класса вместо одного логического класса, каждый класс не требует никаких значений и поэтому может быть различен просто по идентификатору класса (0 или 1). Я считаю, что это приводит к значительным преимуществам скорости внутри Ruby engine, потому что внутренне Ruby может обрабатывать TrueClass и FalseClass как длинные значения, которые требуют нулевого перевода из их значения ID, тогда как логический объект должен быть удален, прежде чем он может быть оценен.

так как все, кроме false и nil значение true в Ruby по умолчанию, вам нужно будет только добавить парсинг строки.

что-то вроде этого может работать:

class Object

  ## Makes sure any other object that evaluates to false will work as intended,
  ##     and returns just an actual boolean (like it would in any context that expect a boolean value).
  def trueish?; !!self; end

end

class String

  ## Parses certain strings as true; everything else as false.
  def trueish?
    # check if it's a literal "true" string
    return true if self.strip.downcase == 'true'

    # check if the string contains a numerical zero
    [:Integer, :Float, :Rational, :Complex].each do |t|
      begin
        converted_number = Kernel.send(t, self)
        return false if converted_number == 0
      rescue ArgumentError
        # raises if the string could not be converted, in which case we'll continue on
      end
    end

    return false
  end

end

при использовании, это даст вам:

puts false.trueish?   # => false
puts true.trueish?    # => true
puts 'false'.trueish? # => false
puts 'true'.trueish?  # => true
puts '0'.trueish?     # => false
puts '1'.trueish?     # => true
puts '0.0'.trueish?   # => false
puts '1.0'.trueish?   # => true

Я считаю, что часть "большой идеи" за Ruby-это просто сделать поведение, которое вы хотите, присущее вашей программе( например, логический разбор), а не создание полностью инкапсулированного класса, который живет в своем собственном мире пространства имен (например BooleanParser).

в Ruby nil и false являются ложными, а все остальное правда. Следовательно, нет необходимости в определенном булевом классе.

Вы можете попробовать это :

if 5
  puts "5 is true"
end

5 оценивается как true

if nil
    puts "nil is true"
else
    puts "nil is false"
end

выведет "nil is false"

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

Как сказал вам Монгус понг, когда вы пишете "если", вы просите интерпретатора оценить вещь а потом ветка. Если бы у вас был логический класс, вам пришлось бы преобразовать оценку вещь в булево до ветвление (более одного шаг.)

помните, что такое преобразование ->Boolean будет доступно как метод Ruby в классе Boolean. Этот метод может быть изменен динамически, как и любой другой метод Ruby, что позволяет разработчику полностью испортить вещи (что не так серьезно), но ясно, что это не позволит интерпретатору оптимизировать тесты, как они должны.

вы понимаете, что это заменит несколько операций с инструкциями процессора полным вызовом метода, что дорого в Ruby (помните о методе" отправить " обработки)...

Как говорили другие, вы можете "залатать" Рубин. Создайте свой собственный класс. Вот что я придумал. Методы в классе Boolean немного глупы, но они могут быть полезны программно в какой-то момент.

class Boolean
  def self.new(bool)
    bool
  end

  def self.true
    true
  end

  def self.false
    false
  end
end

class FalseClass
  def is_a?(other)
    other == Boolean || super
  end

  def self.===(other)
    other == Boolean || super
  end
end

class TrueClass
  def is_a?(other)
    other == Boolean || super
  end

  def self.===(other)
    other == Boolean || super
  end
end

Comments

    Ничего не найдено.