Why does Ruby have TrueClass and FalseClass instead of a single Boolean class?

I worked on serializing values ​​when I found out about it. Ruby has the TrueClass and FalseClass , but it does not have the Boolean class. I would like to know why this is.

I see some advantages when using Boolean ; for example, parsing can be centralized on it.

Ruby developers are smarter than me, so there must be many good reasons that I just don't see. But now it seems to me that OneClass and TwoClass instead of Fixnum .

+64
ruby language-design
Jul 07 '10 at 8:15
source share
8 answers

Matz himself seems to have answered this question in a 2004 mailing list message.

A short version of his answer: "right now it is working fine, adding a boolean does not give any advantage."

Personally, I do not agree with this; the above “string parsing” is one example. Another thing is that when you apply a different call to a variable depending on its type (for example, the yml parser), which has the class "Boolean", this is convenient - it removes one "if". It also looks more correct, but it is a personal opinion.

+19
Jul 12 '10 at 17:51
source share

The purpose of a class is to group similar objects or objects with similar behavior together. 1 and 2 very similar, so it’s completely reasonable for them to be in the same class. true and false , however, are not alike. In fact, the whole point is that they are completely opposite to each other and have the opposite behavior. Therefore, they do not belong to the same class.

Can you give an example of what common behavior you would apply in a Boolean class? I can’t think of anything.

Let's just look at the behavior that TrueClass and FalseClass have: there are exactly four methods. No more. And in each case, these two methods do the opposite. How and why did you put this in one class?

Here you implement all these methods:

 class TrueClass def &(other) other end def |(_) self end def ^(other) !other end def to_s 'true' end end 

And now the other way around:

 class FalseClass def &(_) self end def |(other) other end def ^(other) other end def to_s 'false' end end 

Of course, in Ruby there is a lot of “magic” that happens behind the scenes, and in fact it is not handled by TrueClass and FalseClass , but rather is difficult to interpret. Things like if , && , || and ! . However, in Smalltalk, from which Ruby has borrowed a lot, including the concept of FalseClass and TrueClass , they are all implemented in the same way as methods, and you can do the same in Ruby:

 class TrueClass def if yield end def ifelse(then_branch=->{}, _=nil) then_branch.() end def unless end def unlesselse(_=nil, else_branch=->{}) ifelse(else_branch, _) end def and yield end def or self end def not false end end 

And again the opposite:

 class FalseClass def if end def ifelse(_=nil, else_branch=->{}) else_branch.() end def unless yield end def unlesselse(unless_branch=->{}, _=nil) ifelse(_, unless_branch) end def and self end def or yield end def not true end end 

A few years ago, I wrote the above just for fun, and even published it . Aside from the fact that the syntax looks different since Ruby uses special operators, while I use only methods, it behaves exactly like the built-in Ruby operators. In fact, I actually took the RubySpec conformance checking method and ported it to my syntax and it passes.

+57
Jul 07 2018-10-07T00:
source share

Quoting Matz at the Ruby forum (2013) :

... There is nothing true and false commonly used, so there is no Boolean class. Also, in Ruby, everything behaves like a boolean value ....

+4
Mar 31 '14 at 13:31
source share

true and false can be controlled by a boolean class that contains several values, but then the class object must have internal values ​​and, therefore, must be deleted with each use.

Instead, Ruby treats true and false as long values ​​(0 and 1), each of which corresponds to the type of the object class (FalseClass and TrueClass). Using two classes instead of one Boolean class, each class does not require any values ​​and therefore can be distinguished simply by its class identifier (0 or 1). I believe that this leads to significant speed advantages inherent in the Ruby internal mechanism, since internally Ruby can handle TrueClass and FalseClass as long values ​​that require zero translation from their ID value, whereas the logical object must be deleted before it can be estimate,

+3
Jul 07 '10 at 9:15
source share

Since all but false and nil default to true in Ruby, you only need to add parsing to String.

Something like this might work:

 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 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 

When used, this will give you:

 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 

I believe that part of the “big idea” behind Ruby is simply to make the behavior you desire inherent in your program (such as logical parsing), while creating a fully encapsulated class that lives in its own world namespaces (e.g. BooleanParser).

+3
Mar 22 '11 at 1:08
source share

In Ruby, nil and false are false, and everything else is true. Therefore, there is no need for a specific Boolean class.

You can try:

 if 5 puts "5 is true" end 

5 is true

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

It will print "nil is false"

+1
Jul 07 '10 at 8:18
source share

The main reason is simply the fact that it is much faster and easier to implement Boolean expressions than at present than with a Boolean class that would involve a conversion.

As Mongus Pong told you, when you write "if", you ask the interpreter to evaluate the thing and then respond. If you have a Boolean class, you will need to convert the evaluation of the thing to a Boolean before branching (one more step).

Remember that such a -Boolean conversion will be available as a Ruby method in a boolean class. Then this method could be dynamically changed, like any other Ruby method, allowing the developer to completely ruin things (which is not so serious), but this obviously does not allow the interpreter to optimize the tests as they should.

You understand that it will replace several operations with CPU instructions with a full method call, which is expensive in Ruby (remember the processing of the submit method) ...

+1
Jul 07 '10 at 11:45
source share

As others have said, you can “plan” Ruby. Create your own class. Here is what I came up with. Methods in a boolean class are a little stupid, but at some point they may be useful programmatically.

 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 
0
Mar 22 '17 at 22:48
source share



All Articles