Feature #12515
closedCreate "Boolean" superclass of TrueClass / FalseClass
Description
Since Ruby 2.4 is unifying Bignum/Fixnum into Integer (https://bugs.ruby-lang.org/issues/12005), it seems reasonable to do something similar for TrueClass / FalseClass, and create a proper Boolean hierarchy. The implementation would be fairly straightforward and should be back compat unless someone already has a "Boolean" class at toplevel out there.
Given the compatibility implications of Integer, this Boolean proposal is even less intrusive.
Sample implementation:
class Boolean < BasicObject; end
class TrueClass < Boolean; end
class FalseClass < Boolean; end
Updated by shyouhei (Shyouhei Urabe) over 8 years ago
Loren Segal wrote:
should be back compat unless someone already has a "
Boolean
" class at toplevel out there.
You failed here.
https://github.com/search?l=ruby&q=%22class+Boolean%22&type=Code
https://rubygems.org/search?query=Boolean
I guess it's too late.
Updated by olivierlacan (Olivier Lacan) over 8 years ago
Shyouhei Urabe wrote:
You failed here.
This admittedly could be lost in translation but I don't think this a very nice way to react to Loren's proposal. He didn't fail here. He just proposed something. You either think it's a good idea or a bad idea. I wish you could provide your opinion a bit more kindly.
https://github.com/search?l=ruby&q=%22class+Boolean%22&type=Code
https://rubygems.org/search?query=BooleanI guess it's too late.
I can change the search query to Integer
and provide similarly dubious reasons why Integer
would be bad idea:
https://github.com/search?l=ruby&q=%22class+Integer%22&type=Code
https://rubygems.org/search?query=Integer
I don't think this is very solid counterpoint.
Updated by lsegal (Loren Segal) over 8 years ago
Shyouhei Urabe wrote:
https://github.com/search?l=ruby&q=%22class+Boolean%22&type=Code
https://rubygems.org/search?query=BooleanI guess it's too late.
As Olivier pointed out, isn't this an argument to revert the Integer
patch? Why is the Integer
change okay but not Boolean
?
Updated by lsegal (Loren Segal) over 8 years ago
edit: as a sidenote, adding a Boolean
class to Ruby-core is unlikely to break any of the linked code, because Ruby is just defining an empty Boolean
class. Existing libraries will just re-open the class as normal.
Updated by djberg96 (Daniel Berger) over 8 years ago
This was brought up in the past a lot:
http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/96321
http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/186881
There's also this: http://stackoverflow.com/questions/3192978/why-does-ruby-have-trueclass-and-falseclass-instead-of-a-single-boolean-class
Updated by shyouhei (Shyouhei Urabe) over 8 years ago
- I'm not a big fan of
Integer
, too. However, -
Integer
has been there since the beginning. It was just not used before. You are always free to reopen this class.Boolean
on the other hand, is something new. The situation is different. - Because most wild
Boolean
implementation I have seen inheritsObject
(or depending on projectActiveRecord::Base
), I'm sorry I guess Loren's suggested implementation that inheritsBasicObject
won't interface.
Updated by shugo (Shugo Maeda) over 8 years ago
At http://qiita.com/yatemmma/items/3597a0e20556fb846d3f, Matz explained the reason why Ruby doesn't have Boolean.
-
true
andfalse
are just representative samples of boolean values. - There is no method to be defined in
Boolean
(e.g., implementations ofTrueClass#&
andFalseClass#&
are different). - The use case of
Boolean
is therefore limited tokind_of?
checks, and it prevents duck typing.
However Boolean
might be useful to extend true
and false
in user code (e.g., refining Boolean
).
Another use case is type checking system, but it might not be a good idea to consider a class a type.
Updated by lsegal (Loren Segal) over 8 years ago
In reality it's very common to treat true
/false
as a separate thing. The "everything is boolean" argument falls apart when you have something like var args in a method declaration and you want to perform distinct operations based on the actual value.
This actually comes up fairly often:
https://github.com/search?p=2&q=is_a%3F+TrueClass&ref=searchresults&type=Code&utf8=%E2%9C%93
And that's only the checks for is_a?
syntax, because GitHub cannot search for "TrueClass === x
" style code. But if it's an anti-pattern, it's an extremely common one.
I didn't realize about Integer being around though, that certainly changes things.
Updated by duerst (Martin Dürst) over 8 years ago
Loren Segal wrote:
This actually comes up fairly often:
https://github.com/search?p=2&q=is_a%3F+TrueClass&ref=searchresults&type=Code&utf8=%E2%9C%93
And that's only the checks for
is_a?
syntax, because GitHub cannot search for "TrueClass === x
" style code. But if it's an anti-pattern, it's an extremely common one.
The search results aren't very convincing to me. Where there's a Boolean
class
or module
, it's usually really tiny. And there are checks for TrueClass
and FalseClass
that I'd write as checks for true
and false
, which would make the code a lot shorter.
Actually, because both true
and false
are singletons, TrueClass
and FalseClass
look like overkill; in Ruby's ducktyping world, most if not all things would work just as well with the necessary methods for true
and false
being defined directly as singleton methods on true
and false
.
Updated by nobu (Nobuyoshi Nakada) over 8 years ago
Let's leave TrueClass
/FalseClass
!!
Updated by sawa (Tsuyoshi Sawada) over 8 years ago
Martin Dürst wrote:
Actually, because both
true
andfalse
are singletons,TrueClass
andFalseClass
look like overkill; in Ruby's ducktyping world, most if not all things would work just as well with the necessary methods fortrue
andfalse
being defined directly as singleton methods ontrue
andfalse
.
My understanding is that defining a singleton method on an object creates a singleton class for that object (and the method is actually an instance method of the singleton class). And in case of true
, false
or nil
, the singleton classes are in fact the classes in question:
true.singleton_class # => TrueClass
false.singleton_class # => FalseClass
nil.singleton_class # => NilClass
so there is no way to get rid of these classes. We don't need to worry as
Nobuyoshi Nakada wrote:
Let's leave
TrueClass
/FalseClass
!!
And by the way for the Boolean
class proposed in this thread, it surely is un-useful.
Updated by matz (Yukihiro Matsumoto) over 8 years ago
- Status changed from Open to Rejected
Rejected for several reasons:
- many gems and libraries had already introduced
Boolean
class. I don't want to break them. -
true
andfalse
are the only representative of true-false values. In Ruby.nil
andfalse
are falsy values, and everything else is a true value. There's no meaning for having a superclass ofTrueClass
andFalseClass
asBoolean
.
Matz.
Updated by shyouhei (Shyouhei Urabe) about 8 years ago
- Has duplicate Bug #12827: Add Boolean data type. added
Updated by ioquatix (Samuel Williams) about 8 years ago
The fact that so many gems are introducing "class Boolean
" is an argument FOR it not AGAINST it, IMHO. Because when this code is loaded together, it might behave strangely if there is no shared meaning for "class Boolean
".
Having a Boolean(String)
constructor would be useful.
Having a class named Boolean
would make things more readable, for example here: http://sequel.jeremyevans.net/rdoc/files/doc/schema_modification_rdoc.html#label-Column+types - you can see that because there is no Boolean
class, they resort to, IMHO quite a strange naming convention, using either TrueClass
or FalseClass
.
The naming of TrueClass
and FalseClass
are also inconsistent with other names, e.g. it's not IntegerClass
or FloatClass
or StringClass
. It's a little bit ugly. (EDIT: or ZeroClass
, OneClass
, etc :)
There's no meaning for having a superclass of TrueClass and FalseClass as Boolean
I believe you are wrong on this point. There is meaning.
The meaning is that "This variable is of class Boolean
".
There is one example I can think of:
#!/usr/bin/env ruby
x = true
# x = false
case x
when TrueClass
puts "trueclass"
when FalseClass
puts "falseclass"
# How can we implement this?
# when Boolean
end
Situations were this kind of logic comes up include serialisation and deserialisation libraries, data modelling, etc.
Updated by phluid61 (Matthew Kerwin) about 8 years ago
Samuel Williams wrote:
The fact that so many gems are introducing "
class Boolean
" is an argument FOR it not AGAINST it, IMHO. Because when this code is loaded together, it might behave strangely if there is no shared meaning for "class Boolean
".
But that's how things already are, and the market deals with it just fine. Adding a core 'Boolean
' class means every existing implementation, even those only ever used in isolation, will suddenly have a conflict.
There's no meaning for having a superclass of TrueClass and FalseClass as Boolean
I believe you are wrong on this point. There is meaning.
The meaning is that "This variable is of class Boolean".
There is one example I can think of:
#!/usr/bin/env ruby x = true # x = false case x when TrueClass puts "trueclass" when FalseClass puts "falseclass" # How can we implement this? # when Boolean end
Situations were this kind of logic comes up include serialisation and deserialisation libraries, data modelling, etc.
If that was:
case x
when Boolean
#do something
end
What "something" would you do that is identical for both True
and False
? Or put another way, what method would you define inside class Boolean
that is useful to both True
and False
? This comes back to one of Ruby's basic OO-tenets: that classes have shared functionality, not a shared type.
Updated by ioquatix (Samuel Williams) about 8 years ago
But that's how things already are, and the market deals with it just fine.
Well, I know you are being metaphorical ("market deals with it"). But this is not really a case of a market, and I prefer DRY for many reasons. There should be one correct implementation and it makes sense for it to be within Ruby.
To be explicit about it: If I include two gems, and they both define "class Boolean
", and they collide for some reason, it's a problem for me, and it might not even be an obvious problem.
What "something" would you do that is identical for both True and False?
Sometimes you need to handle multiple data types this way because the functionality is on core classes that you don't want to extend. It's similar to how type classes work in Haskell.
So, as a basic example, sometimes you want to be declarative about, say, an API:
format_response(name: String, age: Integer, happy: Boolean)
Another example of this would be libraries like optparse, slop, sequel, etc, where they'd like to declaratively specify that something is a Boolean, e.g.
option '--foo', type: Boolean
# or
create_table :foo do |t|
t.happy type: Boolean
end
Another use case would be where you want to do validation, conversion or deal with a type as specified by the user, e.g.
case @type
when Integer
Integer(result)
when Float
Float(result)
when Boolean
Boolean(result)
end
Unfortunately in Ruby, the type constructors (Kernel.Integer
) are free functions, not part of the class, e.g you can't write Integer.parse(input)
. You need to write (verbosely on purpose) Kernel.Integer(input)
. It's not very OO.
Another case would be handling the above, e.g. Boolean.parse(input)
or Kernel.Boolean(input)
. It would make sense if they could turn the string representations into boolean values and throw an ArgumentError
if not convertable.
Updated by ioquatix (Samuel Williams) about 8 years ago
It's also interesting to note, so many people are working around this:
Searching on github for:
"is_a? TrueClass FalseClass" gives 90,000 results.
https://github.com/search?p=2&q=is_a%3F+TrueClass&ref=searchresults&type=Code&utf8=✓
"module Boolean TrueClass FalseClass" gives 63,000 results.
https://github.com/search?utf8=✓&q=module+Boolean+TrueClass+FalseClass&type=Code&ref=searchresults
Even I'm surprised by the number of people working around this issue!
Updated by rrroybbbean (RRRoy BBBean) about 8 years ago
The terms "truthy" and "falsey" were used by Douglas Crockford in his
series of JavaScript lectures at Yahoo about 5 years ago. A value is
"truthy" if treated as true by a conditional. A value is "falsey" if
treated as false by a conditional.
Ruby has possibly the simplest, cleanest and easiest to use distinction
between "truthy" and "falsey" values of any programming language: nil
and false
are falsey, everything else is truthy.
Compare Ruby's to PHP's or JavaScript's allocation of truthy and falsey,
where empty strings and empty arrays and even zero can be falsey. If 0
is falsey, should 0.0
be false? What about rounding errors? How about
complex numbers? expressed in rectangular notation? expressed in polar
notation? How about multidimensional arrays that contain no values other
than arrays? How about empty dictionaries? Should they truthy or falsey?
The richer the language and it's data structures, the more vexing these
issues become.
Ruby has reduced the confusion to a minimum by keeping the falsey values
to a minimum: false
and nil
. Everything else is truthy. And Ruby
accomplishes this without a Boolean
class. Adding a Boolean
class to
Ruby is not necessary, and it would be profoundly inelegant.
I quote the definition of elegance provided by Alex W. White in his 'The
Elements of Graphic Design': "Distill the essential from the mass of
confusing muchness. Nothing may be missing and nothing may be
extraneous. This is the definition of elegance."
There is also a well-know translation of a quotation by the famous
French pioneer in aviation Antoine de Saint-Exupéry (as translated by
Lewis Galantière): "... perfection is finally attained not when there is
no longer anything to add, but when there is no longer anything to take
away ..."
Please don't add a Boolean
class to Ruby; it doesn't need a Boolean
class.
Updated by phluid61 (Matthew Kerwin) about 8 years ago
Samuel Williams wrote:
But that's how things already are, and the market deals with it just fine.
Well, I know you are being metaphorical ("market deals with it"). But this is not really a case of a market, and I prefer DRY for many reasons. There should be one correct implementation and it makes sense for it to be within Ruby.
It's not a metaphor, it's the real world. Ruby gems exist in open competition, and developers have the opportunity to choose between (or create alternatives to) any available gems in the ecosystem.
If there should be one "correct" implementation, why do we have gems at all? Everything should be in the core. And that's without even starting the big argument about which approach should be considered "correct." (Anyone who says "N"
is falsy-y in all cases is going to have some serious arguing ahead of them.)
To be explicit about it: If I include two gems, and they both define "
class Boolean
", and they collide for some reason, it's a problem for me, and it might not even be an obvious problem.
Indeed. That goes back to an open marketplace and market forces. You say, "If I do this..." but I say, "People already live with that possibility and seem to be surviving just fine."
What "something" would you do that is identical for both True and False?
Sometimes you need to handle multiple data types this way because the functionality is on core classes that you don't want to extend. It's similar to how type classes work in Haskell.
[snip]
Everything you've listed there is a type. Ruby doesn't do types like that. You're conflating the class hierarchy with types.
Unfortunately in Ruby, the type constructors (
Kernel.Integer
) are free functions, not part of the class, e.g you can't writeInteger.parse(input)
. You need to write (verbosely on purpose)Kernel.Integer(input)
. It's not very OO.
They're not constructors; Integer
s (well, Fixnum
s) are singleton and cannot be instantiated. The methods you're talking about are for coercion. (And very specific coercion at that.)
If you want to talk about OO, the casting methods (e.g. #to_i
) are defined on the object-to-be-recast, or an intermediate expert. The destination class doesn't and shouldn't have responsibility to understand every possible class or type of object, and know how to convert them all to an instance of itself. There are all sorts of anti-patterns in there. (Said another way: a String
should know whether it represents a 'true' or 'false' value, or there should be an object that knows just enough about String
s and booleans to be able to manage the conversion.)
Another case would be handling the above, e.g.
Boolean.parse(input)
orKernel.Boolean(input)
. It would make sense if they could turn the string representations into boolean values and throw anArgumentError
if not convertable.
I posit that it should be something like String#to_bool
, since the String is the thing that knows whether and how it represents a boolean value.
There is no value in defining a Boolean
superclass of both True
and False
.
Updated by nobu (Nobuyoshi Nakada) about 8 years ago
Samuel Williams wrote:
Having a class named
Boolean
would make things more readable, for example here: http://sequel.jeremyevans.net/rdoc/files/doc/schema_modification_rdoc.html#label-Column+types - you can see that because there is noBoolean
class, they resort to, IMHO quite a strange naming convention, using eitherTrueClass
orFalseClass
.
It's a choice by that library author.
They are not classes but methods, there can be Boolean
method in the library.
Not providing such method is the choice by the author.
The naming of
TrueClass
andFalseClass
are also inconsistent with other names, e.g. it's notIntegerClass
orFloatClass
orStringClass
. It's a little bit ugly. (EDIT: orZeroClass
,OneClass
, etc :)
Indeed.
We don't need the names for singleton classes of true
, false
, and nil
, and should remove them all.
Updated by rosenfeld (Rodrigo Rosenfeld Rosas) about 8 years ago
I'd just like to add a real situation where I missed a Boolean
class recently.
A web request takes an array of values in a JSON encoded string and before processing the data the server-side handler will try to validate the input by comparing the elements type. If Boolean
existed, the validation rule would be something like:
input = JSON.parse(params['value'])
raise InvalidInput, 'size must be 6' unless input.size == 6
raise InvalidInput, "types don't match" unless input.map(&:class) ==
[String, String, String, Boolean, String, Boolean]
As you can imagine, the validation took more effort without the existence of Boolean
. Something like:
input.map{|x| x == false || x == true ? :boolean : x.class } ==
[String, String, String, :boolean, String, :boolean]
Updated by rosenfeld (Rodrigo Rosenfeld Rosas) about 8 years ago
Actually, this isn't a good example as it would return TrueClass
or FalseClass
rather than Boolean
...
Updated by rosenfeld (Rodrigo Rosenfeld Rosas) about 8 years ago
Maybe something like:
input.zip([String, String, String, Boolean, String, Boolean]).all?{|(i, c)| c === i }
Updated by ioquatix (Samuel Williams) about 8 years ago
It's a choice by that library author. They are not classes but methods, there can be
Boolean
method in the library.
Nobu, you are not looking deep enough.
The author makes methods to produce the types. The type name must be the same. My feeling is that if a Boolean
type existed, they would prefer it.
"Distill the essential from the mass of
confusing muchness. Nothing may be missing and nothing may be
extraneous. This is the definition of elegance."
Yes, and if you apply this logic, why have two classes when one would be better in every way?
There is no value in defining a
Boolean
superclass of bothTrueClass
andFalseClass
.
There is value in the check x.is_a? Boolean
. The value is in the check itself, finding out if x contains [true, false]. And the value is in the consistency that there is a single class name "Boolean
which is polymorphic over the set of classes Integer
, Float
, Numeric
, String
, etc, which are used over and over again in code which does formatting, type checking, serialisation, deserialisation, database modelling, etc.
The evidence is overwhelming. There are 150,000 instances of code working around the lack of Boolean
on GitHub. At what point do you draw the line and say "Yeah, enough people are doing this, it might make sense to bring this into the core language".
No other language structures booleans around a "TrueClass
" and "FalseClass
":
- Python has
bool
data type. - C has
#include <stdbool.h>
- C++ has
bool
- Java has
bool
andclass Boolean
- JavaScript has
Boolean
- Smalltalk has
Boolean
- CLISP has
BOOLEAN
but I say, "People already live with that possibility and seem to be surviving just fine."
Is Ruby a language just to survive or is it a language to provide the tools programmers need to be happy?
I say, that every person who wrote their own Boolean class, wasted an hour of their time trying to figure it out. On GitHub, there are 2,080,658 results for "class Boolean". I know it's an overestimate, but that gives us an upper bound of 228+ years of programmer time. Matz, how can you live with yourself :D (purely for comic effect, honestly we all love you).
Updated by phluid61 (Matthew Kerwin) about 8 years ago
Samuel Williams wrote:
There is no value in defining a
Boolean
superclass of bothTrueClass
andFalseClass
.There is value in the check
x.is_a? Boolean
. The value is in the check itself, finding out if x contains [true, false]. And the value is in the consistency that there is a single class name "Boolean
which is polymorphic over the set of classesInteger
,Float
,Numeric
,String
, etc, which are used over and over again in code which does formatting, type checking, serialisation, deserialisation, database modelling, etc.
You keep saying things like "polymorphic," but you still haven't answered the question which is fundamental to this whole debate: what method would you define on class Boolean
that applies identically to both TRUE
and FALSE
?
An object's .class
is not the same as its type.
If they never quack the same, they aren't ducks. A class that doesn't define a #quack method is not a useful class, in the Ruby sense.
No other language structures booleans around a "TrueClass" and "FalseClass":
- Python has
bool
data type.- C has
#include <stdbool.h>
- C++ has
bool
- Java has
bool
andclass Boolean
- JavaScript has
Boolean
- Smalltalk has
Boolean
- CLISP has
BOOLEAN
As has been mentioned already, TrueClass
and FalseClass
(and NilClass
) are just named eigenclasses of the objects TRUE
and FALSE
(and NIL
). There's no "structure" around them beyond the fact that every object (including the three listed above) has one; these three just happen to have a little quirk in their inheritance.
Perhaps it would be better if TRUE.class
(etc.) returned Object
; being an instance of the eigenclass is rather confusing.
but I say, "People already live with that possibility and seem to be surviving just fine."
Is Ruby a language just to survive or is it a language to provide the tools programmers need to be happy?
(Semantics: "surviving just fine" implies satisfaction and comfort (i.e. happiness.) That notwithstanding:)
The latter, if the "programmers" in question are Matz. Ruby isn't designed to make Java or C++ or 8086 programmers happy, it's designed for Ruby programmers. In Ruby class is not type, and type is defined by behaviour. You have to learn this if you want to be a happy Ruby programmer.
Updated by phluid61 (Matthew Kerwin) about 8 years ago
Rodrigo Rosenfeld Rosas wrote:
I'd just like to add a real situation where I missed a
Boolean
class recently.A web request takes an array of values in a JSON encoded string and before processing the data the server-side handler will try to validate the input by comparing the elements type. If
Boolean
existed, the validation rule would be something like:input = JSON.parse(params['value']) raise InvalidInput, 'size must be 6' unless input.size == 6 raise InvalidInput, "types don't match" unless input.map(&:class) == [String, String, String, Boolean, String, Boolean]
As you can imagine, the validation took more effort without the existence of
Boolean
. Something like:input.map{|x| x == false || x == true ? :boolean : x.class } == [String, String, String, :boolean, String, :boolean]
There's a potential religious argument here about validating against the schema before/after deserialising. Pragmatically I understand that we have a JSON parser and we don't have a JSON validator, so it's much easier to validate-later. To that end, it's also really easy to monkey-patch your way to happiness:
module Boolean; end
class TrueClass; include Boolean; end
class FalseClass; include Boolean; end
[true, false, 1, nil].select {|x| Boolean === x } #=> [true, false]
There's also the fact that just because JSON has a boolean type doesn't mean Ruby has to. Ruby has procs, but you can't serialise them into JSON.
Updated by rrroybbbean (RRRoy BBBean) about 8 years ago
Joel on Software "Don't Let Architecture Astronauts Scare You" by Joel
Spolsky http://www.joelonsoftware.com/articles/fog0000000018.html
Updated by nobu (Nobuyoshi Nakada) about 8 years ago
Rodrigo Rosenfeld Rosas wrote:
Maybe something like:
Boolean = [true, false]
input.zip([String, String, String, Boolean, String, Boolean]).all?{|(i, c)| c === i }
Updated by nobu (Nobuyoshi Nakada) about 8 years ago
Samuel Williams wrote:
It's a choice by that library author. They are not classes but methods, there can be
Boolean
method in the library.Nobu, you are not looking deep enough.
It seems specific to the context, and should be defined there.
Updated by rosenfeld (Rodrigo Rosenfeld Rosas) about 8 years ago
Nobuyoshi Nakada wrote:
Rodrigo Rosenfeld Rosas wrote:
Maybe something like:
Boolean = [true, false]
input.zip([String, String, String, Boolean, String, Boolean]).all?{|(i, c)| c === i }
This doesn't seem to work as I just tested in irb: [true, false] === true => false
Updated by ioquatix (Samuel Williams) about 8 years ago
It seems specific to the context, and should be defined there.
Yeah but it's not. 2,080,658 instances of code on GitHub disagree with you. It's not my personal opinion, it's tangible evidence. But what evidence do you have to support NOT adding Boolean
? I can't think of any good reason why you shouldn't add it.
Updated by nobu (Nobuyoshi Nakada) about 8 years ago
Matz has explained the reasons.
Updated by phluid61 (Matthew Kerwin) about 8 years ago
Samuel Williams wrote:
[...] But what evidence do you have to support NOT adding Boolean? I can't think of any good reason why you shouldn't add it.
Ignoring most of the "bad" reasons in this thread, how about reiterating this one:
If Ruby core were to introduce class Boolean
, a lot of those 2 million libraries you refer to would break, because they use module Boolean
and module
can't re-open a class.
And who knows how many of the class Boolean
peoples' code would also break if instance methods on their previously-safe classes were suddenly inherited by TRUE
and FALSE
?
Updated by ioquatix (Samuel Williams) about 8 years ago
Matthew, I ask you to find one of those examples that would break by introducing the following to core Ruby:
if $VERBOSE and defined? Boolean
warn "Top level Boolean is deprecated, please update your code"
end
class Kernel::Boolean
end
class TrueClass < Kernel::Boolean
end
class FalseClass < Kernel::Boolean
end
Finally, if this really is the issue, then either 1/ put it inside require 'boolean'
or 2/ release with ruby 3.0 - there are plenty of options, one does not need to be so pessimistic.
Personally, I find Matz argument about duck typing superficial. Because, this isn't a case of duck typing (abstraction) but set membership (is this either true or false). We already have useful checks for these things for Integer, Float, Numeric, String, etc. Why not Boolean? It's inconsistent.
Updated by duerst (Martin Dürst) about 8 years ago
Just a side question:
Samuel Williams wrote:
class Kernel::Boolean
end
Why do you use Kernel::Boolean and not just Boolean?
Updated by phluid61 (Matthew Kerwin) about 8 years ago
Samuel Williams wrote:
Finally, if this really is the issue, then either 1/ put it inside
require 'boolean'
or 2/ release with ruby 3.0 - there are plenty of options, one does not need to be so pessimistic.
It's just one of the issues, but it's the one backed by the same numbers you seem to think are the be-all and end-all. Anyone can munge code to not conflict with existing implementations. (Kernel::Boolean
? Really?)
Personally, I find Matz argument about duck typing superficial. Because, this isn't a case of duck typing (abstraction) but set membership (is this either true or false). We already have useful checks for these things for Integer, Float, Numeric, String, etc. Why not Boolean? It's inconsistent.
It's because, as has already been stated, Integer#+ and Float#ceil are methods with implementations shared by all instances of those classes. There is no such method to define on Boolean. And if it's all about set membership, why is NIL
not an instance of Boolean? (It is false) Why not all other objects? (They are true)
You are free to define whatever arbitrary sets you like, in whatever context it's appropriate. Put "Y"
in the truthy set and "N"
in the falsey, I don't care. But that doesn't mean you should push those (or any) arbitrary set memberships into the core.
Updated by ioquatix (Samuel Williams) about 8 years ago
Why do you use Kernel::Boolean and not just Boolean?
Some gems define
class Boolean
end
class TrueClass; include Boolean; end
class FalseClass; include Boolean; end
and some gems define:
module Boolean
end
class TrueClass; include Boolean; end
class FalseClass; include Boolean; end
If we defined our own class Boolean
it would conflict with users (not that many) who are defining module Boolean
. So, instead we define Kernel::Boolean
. It's just one option. A simple way of understanding that is that Kernel
is kind of a top level scope for name resolution so it works just fine.
Personally I don't think it's important in this case, people defining module Boolean
in the global scope are categorically doing the wrong thing, but that's just my opinion. However, the sample implantation I gave works, does not collide with any existing implementation and would be perfectly suitable going forward, where in Ruby 3 it could be renamed to class Boolean
and all people have received sufficient warning.
It's just one of the issues, but it's the one backed by the same numbers you seem to think are the be-all and end-all.
The numbers are really just there to support the hypothesis that lots of people are working around the lack of class Boolean
in core. The main issue here being a lack of consistency with other data types and specifically x.is_a? Boolean
. Lot of people are doing this - there can be no disagreement here. It's an implementation detail whether methods are defined on class Boolean
or class TrueClass
and class FalseClass
so Matz' argument does not resonate with me. I'm not arguing about implementation. I'm simply supporting moving into Ruby core what is already standard practice by 2 million examples.
Updated by nobu (Nobuyoshi Nakada) about 8 years ago
Kernel
is included by Object
, that is the toplevel namespace, they conflict.
class Kernel::Boolean; end
module Boolean; end #=> Boolean is not a module (TypeError)
Updated by ioquatix (Samuel Williams) about 8 years ago
Nobu, thanks for that clarification. I was not aware of that.
If that's the only issue holding back this feature, I'm sure a workaround can be found that works appropriately.
It might be as simple as going with the more common option class Boolean
and breaking when people define module Boolean
in the global namespace, which in practice is very small percentage, and already represents a problem when people try to include code which does it both ways, and for which the preferred way is most certainly class Boolean
.
Another option is to include in the standard library a boolean.rb
which defines set semantics for what people are already doing. If you include this yourself, and other code breaks, it's your own fault.
Updated by shyouhei (Shyouhei Urabe) about 8 years ago
Samuel Williams wrote:
If that's the only issue holding back this feature.
Sadly no. The reason why this is not accepted is matz do not like the idea. You have to persuade him.
Another option is to include in the standard library a
boolean.rb
which defines set semantics for what people are already doing. If you include this yourself, and other code breaks, it's your own fault.
What's wrong with a gem, in that case? Raise of rubygems made it harder today than past to introduce a new standard library.
Updated by r.smitala (Radovan Smitala) over 7 years ago
You have in some cases true.
There should be some circumstances where implemented Boolean class should be problematic. But many of existed gems just reopen class and life goes on. Rails 5 isn't till now compatible with Ruby 2.4 with introduced Integer class.
I think we can looking on potential Boolean as Integer class. For integer doesn't matter which value represents, one condition is it should be whole number. From almost infinite negative to infinite positive number. But still it is Integer. Whole number is representation of type Integer.
Boolean values are also described. They are represented by true and false. Object which can be just true or false is rightful, and is defined by Boolean type.
Still there should be fallback to FalseClass and TrueClass like for Bignum and Fixnum.
Boolean class is very handy. In coercions, in type checking, in validations, in nice looking and more understandable code, any many more examples.
Yukihiro Matsumoto wrote:
Rejected for several reasons:
- many gems and libraries had already introduced
Boolean
class. I don't want to break them.true
andfalse
are the only representative of true-false values. In Ruby.nil
andfalse
are falsy values, and everything else is a true value. There's no meaning for having a superclass ofTrueClass
andFalseClass
asBoolean
.Matz.
Updated by shyouhei (Shyouhei Urabe) over 7 years ago
Radovan Smitala wrote:
There should be some circumstances where implemented Boolean class should be problematic. But many of existed gems just reopen class and life goes on. Rails 5 isn't till now compatible with Ruby 2.4 with introduced Integer class.
Kind of off topic maybe but can you tell us the Rails 5 story? I was not aware of such thing until now. If you want us to follow how Integer was integrated, there must be lessons to be learned.
Updated by r.smitala (Radovan Smitala) over 7 years ago
Shyouhei Urabe wrote:
Radovan Smitala wrote:
There should be some circumstances where implemented Boolean class should be problematic. But many of existed gems just reopen class and life goes on. Rails 5 isn't till now compatible with Ruby 2.4 with introduced Integer class.
Kind of off topic maybe but can you tell us the Rails 5 story? I was not aware of such thing until now. If you want us to follow how Integer was integrated, there must be lessons to be learned.
Just deprecated warnings for Fixnum and Bignum :) And that is OK. Rails is biggest project/framework/tool in Ruby community. It takes some time to be fully compatible, not only for Integer addition, but all changes. 3 days before was released first public compatible version :)
Updated by byroot (Jean Boussier) 2 months ago
- Related to Feature #20756: Introduce Boolean class added
Updated by hsbt (Hiroshi SHIBATA) 9 days ago
- Related to Feature #20882: Provide Boolean(...) added