For review: PEP 285: Adding a bool type

I'll let this short and sweet PEP speak for itself.
http://python.sourceforge.net/peps/pep-0285.html
PEP: 285 Title: Adding a bool type Version: $Revision: 1.1 $ Last-Modified: $Date: 2002/03/08 15:38:37 $ Author: guido@python.org (Guido van Rossum) Status: Draft Type: Standards Track Created: 8-Mar-2002 Python-Version: 2.3 Post-History: 8-Mar-2002 (python-dev)
Abstract
This PEP proposes the introduction of a new built-in type, bool, with two constants, False and True. The bool type would be a straightforward subtype (in C) of the int type, and the values False and True would behave like 0 and 1 in most respects (e.g. False==0 and True==1 would be true) except repr() and str(). All built-in operations that conceptually return a Boolean result will be changed to return False or True instead of 0 or 1; for example, comparisons and the "not" operator.
Rationale
Most languages eventually grow a Boolean type; even C99 has one. It's useful to be able to tell from a function result that the outcome has Boolean semantics.
Specification
The following Python code specifies most of the properties of the new type:
class bool(int):
def __new__(cls, val=0, _create=0): if _create: # This is nor part of the spec, # just a hack to bootstrap False and True return int.__new__(cls, not not val) elif val: return True else: return False
def __repr__(self): if self: return "True" else: return "False"
__str__ = __repr__
def __and__(self, other): if isinstance(other, bool): return bool(int(self) & int(other)) else: return NotImplemented
__rand__ = __and__
def __or__(self, other): if isinstance(other, bool): return bool(int(self) | int(other)) else: return NotImplemented
__ror__ = __or__
def __xor__(self, other): if isinstance(other, bool): return bool(int(self) ^ int(other)) else: return NotImplemented
__rxor__ = __xor__
False = bool(0, _create=1) True = bool(1, _create=1)
Issues
Because the repr() or str() of a bool value is different from an int value, some code (e.g. doctest-based unit tests) may fail. How much of a backwards compatibility problem this will be, I don't know. If we find this is a real problem, we could add a command-line option to make False and True aliases for 0 and 1 and bool an alias for int.
Copyright
This document has been placed in the public domain.
Local Variables: mode: indented-text indent-tabs-mode: nil fill-column: 70 End:
--Guido van Rossum (home page: http://www.python.org/~guido/)

Do you propose to change the type of "x == y" et. al. from int --> bool? Sounds good to me. In general, I can change my doctests to use assert rather than looking for 1 or 0.
-Dave
----- Original Message ----- From: "Guido van Rossum" guido@python.org To: python-dev@python.org Sent: Friday, March 08, 2002 10:43 AM Subject: [Python-Dev] For review: PEP 285: Adding a bool type

Do you propose to change the type of "x == y" et. al. from int --> bool? Sounds good to me.
Yes.
In general, I can change my doctests to use assert rather than looking for 1 or 0.
Hm, assert is the wrong thing though, since it's optimized away in -O mode. You may have to create your own function "check(x)" that does nothing on true but raises an exception on false, or prints "Yes" or "No", or something like that.
--Guido van Rossum (home page: http://www.python.org/~guido/)

[David Abrahams]
In general, I can change my doctests to use assert rather than looking for 1 or 0.
If you want x-version doctests, you could change
"""
boolean_expect_true
1
boolean_expect_false
0 """
to, e.g.,
"""
boolean_expect_true and 1
1
boolean_expect_false or 0
0 """
Then you won't get hosed by -O (as an assert would do). You may not run doctests with -O today, but the more -O does over time the more important it will become to do so.
Right now running tests under -O mainly protects against logic errors introduced by hiding crucial parts of the code in "if __debug__:" blocks, and few people use __debug__ explicitly now.

----- Original Message ----- From: "Tim Peters" tim.one@comcast.net
[David Abrahams]
In general, I can change my doctests to use assert rather than
looking
for 1 or 0.
If you want x-version doctests, you could change
"""
boolean_expect_true
1
boolean_expect_false
0 """
to, e.g.,
"""
boolean_expect_true and 1
1
boolean_expect_false or 0
0 """
Then you won't get hosed by -O (as an assert would do).
...I guess I can see why you're really intending that
>>> 0 or False False
but
>>> False or 0 0
This sure rubs all my expectations for a bool the wrong way, though. I think I'd better just write my own assertion routine, as Guido suggested. I don't like non-obvious language constructs for something so simple (I'd mention ?: here but I don't need the bruises).
You may not run doctests with -O today, but the more -O does over time the more
important it
will become to do so.
Yes.

[David Abrahams]
...I guess I can see why you're really intending that
>>> 0 or False False
but
>>> False or 0 0
This sure rubs all my expectations for a bool the wrong way, though.
It has much more to do with expectations for what "and" and "or" do. Note that they're not "operators" in Python, they're control structures, and cannot be overridden. Don't mix bools with ints with control structures, and you won't get surprised; "False or 0" returning 0 in Python is no more surprising than that
if False: x = False else: x = 0
sets x to 0, and *oodles* of code relies on that equivalence.
I think I'd better just write my own assertion routine, as Guido suggested. I don't like non-obvious language constructs for something so simple (I'd mention ?: here but I don't need the bruises).
Na, do this:
def bool(e): return e and 'True' or 'False'
Then wrap your true/false expressions in bool() calls. All assuming x-version invariance is important to you. When versions of Python before 2.3 become uninteresting, get rid of the bool() function (and so unmask the builtin of the same name).

----- Original Message ----- From: "Tim Peters" tim.one@comcast.net
It has much more to do with expectations for what "and" and "or" do.
Note
that they're not "operators" in Python, they're control structures,
and
cannot be overridden.
Yes, I realize what's actually going on (and/or are Lisp-y), but as I said, it rubs my expectations for expressions with bool the wrong way.
Don't mix bools with ints with control structures,
That mixing was your suggestion, if I recall <.02 wink>
and you won't get surprised; "False or 0" returning 0 in Python is no
more
surprising than that
if False: x = False else: x = 0
sets x to 0, and *oodles* of code relies on that equivalence.
I think you were the one who taught me the wonderful (x and [y] or [z])[0] trick, so yes, I'm aware of that. On the other hand (I hope I'm a flame-retard now), people shouldn't have to do stuff like that, especially in a world with bool.
In any case, it seems to me that it's been correctly noted that you /will/ see these mixtures for quite some time to come, because of legacy code.
I think I'd better just write my own assertion routine, as Guido suggested. I don't like non-obvious language constructs for
something so
simple (I'd mention ?: here but I don't need the bruises).
Na, do this:
def bool(e): return e and 'True' or 'False'
Then wrap your true/false expressions in bool() calls. All assuming x-version invariance is important to you. When versions of Python
before
2.3 become uninteresting, get rid of the bool() function (and so
unmask the
builtin of the same name).
Harrumph. The builtin doesn't create strings, but bools. I don't think doctest is going to ignore the quotes.
-Dave

[Tim]
Don't mix bools with ints with control structures,
[David Abrahams]
That mixing was your suggestion, if I recall <.02 wink>
Of course: it solved your problem. That you went on to whine about it isn't really my doing <wink>.
... I think you were the one who taught me the wonderful (x and [y] or [z])[0] trick, so yes, I'm aware of that.
Well, I invented that one, so I suppose it's possible. I've never actually used it, though.
On the other hand (I hope I'm a flame-retard now), people shouldn't have to do stuff like that, especially in a world with bool.
Nobody has ever had to do stuff like that; fear of if/else is baffling to me. I supported adding a ?: ternary workalike to Python anyway, and Guido even implemented one, but gave up on it. Unfortunately, the reasons for rejection were never recorded in a PEP.
In any case, it seems to me that it's been correctly noted that you /will/ see these mixtures for quite some time to come, because of legacy code.
Yes. I don't mind them at all.
Na, do this:
def bool(e): return e and 'True' or 'False'
Harrumph. The builtin doesn't create strings, but bools. I don't think doctest is going to ignore the quotes.
Damn, you're right. I'll patch doctest to special-case the snot out of those specific strings <wink>. In the meantime,
def ibool(e): return e and 1 or 0 # or "return operator.truth(e)"
will work across all Pythons forever, or back to 1.4 if you use operator.truth to avoid offending yourself <wink>.

Damn, you're right. I'll patch doctest to special-case the snot out of those specific strings <wink>. In the meantime,
def ibool(e): return e and 1 or 0 # or "return operator.truth(e)"
will work across all Pythons forever, or back to 1.4 if you use operator.truth to avoid offending yourself <wink>.
And will improve doc tests doc readability <wink>.
sorry-I-couldn'-stop-myself-ly y'rs - Samuele.

From: Samuele Pedroni pedroni@inf.ethz.ch
And will improve doc tests doc readability <wink>.
Oops that should have been
And will improve doctest test docstrings readability <wink>.
or doc tests readability <wink>.

[Samuele Pedroni]
And will improve doc tests doc readability <wink>.
[Samuele Pedroni]
Oops that should have been
And will improve doctest test docstrings readability <wink>.
or doc tests readability <wink>.
I don't think David uses doctest in that way -- to my surprise, *most* doctest users don't seem to write documentation at all <wink>.
In the core it doesn't matter: the libraries for a release ship with that release, and only need to work with that release. So s/1/True/ etc is fine there. I don't mind changing stuff like that, and to the contrary think it's valuable to get kicked in the teeth with that output *is* changing with a new release (indeed, automatically catching changes that ordinarily never get caught is one of doctest's primary goals). I think changing stuff like that irritates Guido, though, because he wants to pretend that users don't care what Python displays from release to release<0.9 wink>.

----- Original Message ----- From: "Tim Peters" tim.one@comcast.net To: "Samuele Pedroni" pedroni@inf.ethz.ch Cc: python-dev@python.org Sent: Sunday, March 10, 2002 2:20 AM Subject: RE: [Python-Dev] For review: PEP 285: Adding a bool type
[Samuele Pedroni]
And will improve doc tests doc readability <wink>.
[Samuele Pedroni]
Oops that should have been
And will improve doctest test docstrings readability <wink>.
or doc tests readability <wink>.
I don't think David uses doctest in that way -- to my surprise, *most* doctest users don't seem to write documentation at all <wink>.
s/docteset users/programmers/ ?
I actually do write lots of documentation, and often use small doctest-compatible illustrations, but the problem with that is usually that a really comprehensive test is too big to make a readable comment. These days I don't get to write too much actual Python, so mostly I use doctest to exercise and verify extension modules built with Boost.Python.
-Dave

Guido van Rossum wrote:
PEP: 285 Title: Adding a bool type
This PEP proposes the introduction of a new built-in type, bool, with two constants, False and True. The bool type would be a straightforward subtype (in C) of the int type, and the values False and True would behave like 0 and 1 in most respects (e.g. False==0 and True==1 would be true) except repr() and str(). All built-in operations that conceptually return a Boolean result will be changed to return False or True instead of 0 or 1; for example, comparisons and the "not" operator.
+1000 ;-)
One question: do True/False behave like None, particularly WRT "is"?

PEP: 285 Title: Adding a bool type
[Aahz]
+1000 ;-)
One question: do True/False behave like None, particularly WRT "is"?
That depends on what the meaning of "is" is. (*)
Yes, there will be only one True and one False. That's what the _create flag on the __new__ method was trying to suggest.
(*) Did anyone else notice that in his Python10 paper, Alex Martelli waxed philosophically for an entire paragraph (with references throughout the ages!) on what the meaning of "is" is, without ever mentioning the US Presidency? :-)
--Guido van Rossum (home page: http://www.python.org/~guido/)

>> One question: do True/False behave like None, particularly WRT "is"?
Guido> That depends on what the meaning of "is" is. (*)
Guido> Yes, there will be only one True and one False. That's what the Guido> _create flag on the __new__ method was trying to suggest.
Hmmm... A boolean type can only take on two values. I presume you will expose True and False through builtins. Why would you need a __new__ method or any notiong of "creation"?
Skip

>> One question: do True/False behave like None, particularly WRT "is"? Guido> That depends on what the meaning of "is" is. (*) Guido> Yes, there will be only one True and one False. That's what the Guido> _create flag on the __new__ method was trying to suggest.
Hmmm... A boolean type can only take on two values. I presume you will expose True and False through builtins.
Yes.
Why would you need a __new__ method or any notiong of "creation"?
__new__ must exist in order to support writing
bool(some_expression)
__new__ returns a reference to the existing False or True object, except when it is called in the special internal-only mode that is needed to bootstrap False and True. The __new__ code should really be just this:
def __new__(cls, val=0, _create=0): if val: return True else: return False
except the Python version must be able to create the instances True and False. (Hm, there's another way to create them:
False = int.__new__(bool, 0) True = int.__new__(bool, 1)
I'll change the PEP to use this.)
--Guido van Rossum (home page: http://www.python.org/~guido/)

Guido van Rossum wrote:
I'll let this short and sweet PEP speak for itself.
http://python.sourceforge.net/peps/pep-0285.html
PEP: 285 Title: Adding a bool type Version: $Revision: 1.1 $ Last-Modified: $Date: 2002/03/08 15:38:37 $ Author: guido@python.org (Guido van Rossum) Status: Draft Type: Standards Track Created: 8-Mar-2002 Python-Version: 2.3 Post-History: 8-Mar-2002 (python-dev)
Abstract
This PEP proposes the introduction of a new built-in type, bool, with two constants, False and True. The bool type would be a straightforward subtype (in C) of the int type, and the values False and True would behave like 0 and 1 in most respects (e.g. False==0 and True==1 would be true) except repr() and str(). All built-in operations that conceptually return a Boolean result will be changed to return False or True instead of 0 or 1; for example, comparisons and the "not" operator.
Rationale
Most languages eventually grow a Boolean type; even C99 has one. It's useful to be able to tell from a function result that the outcome has Boolean semantics.
+1.
Specification
The following Python code specifies most of the properties of the new type: class bool(int): def __new__(cls, val=0, _create=0): if _create: # This is nor part of the spec, # just a hack to bootstrap False and True return int.__new__(cls, not not val) elif val: return True else: return False def __repr__(self): if self: return "True" else: return "False" __str__ = __repr__
I don't like this: it will break too much code since there are already two singletons Py_True and Py_False available in Python and these return 1 / 0 resp.
def __and__(self, other): if isinstance(other, bool): return bool(int(self) & int(other)) else: return NotImplemented __rand__ = __and__ def __or__(self, other): if isinstance(other, bool): return bool(int(self) | int(other)) else: return NotImplemented __ror__ = __or__ def __xor__(self, other): if isinstance(other, bool): return bool(int(self) ^ int(other)) else: return NotImplemented __rxor__ = __xor__ False = bool(0, _create=1) True = bool(1, _create=1)
Please adjust Py_True and Py_False (at C level) to be identical to these constants.
Issues
Because the repr() or str() of a bool value is different from an int value, some code (e.g. doctest-based unit tests) may fail. How much of a backwards compatibility problem this will be, I don't know. If we find this is a real problem, we could add a command-line option to make False and True aliases for 0 and 1 and bool an alias for int.
Please, no !
Ideal would be to make bool a subtype of int and True and False two singletons created from 1 and 0 having the bool type: that's simple and backwards compatible.
One idea for a possible addition:
Add boolean support to the array module so that it becomes possible to create arrays of bits.
Copyright
This document has been placed in the public domain.
Local Variables: mode: indented-text indent-tabs-mode: nil fill-column: 70 End:
--Guido van Rossum (home page: http://www.python.org/~guido/)
Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev

def __repr__(self): if self: return "True" else: return "False" __str__ = __repr__
I don't like this: it will break too much code since there are already two singletons Py_True and Py_False available in Python and these return 1 / 0 resp.
But this is the whole point of introducing a new type rather than simply defining True as 1 and False as 0!
False = bool(0, _create=1) True = bool(1, _create=1)
Please adjust Py_True and Py_False (at C level) to be identical to these constants.
Yes, that was the intention.
Issues
Because the repr() or str() of a bool value is different from an int value, some code (e.g. doctest-based unit tests) may fail. How much of a backwards compatibility problem this will be, I don't know. If we find this is a real problem, we could add a command-line option to make False and True aliases for 0 and 1 and bool an alias for int.
Please, no !
Agreed -- I just mentioned it as a possibility if we find too much problems due to the new repr() and str().
Ideal would be to make bool a subtype of int and True and False two singletons created from 1 and 0 having the bool type: that's simple and backwards compatible.
That's what I am proposing.
One idea for a possible addition:
Add boolean support to the array module so that it becomes possible to create arrays of bits.
That's an entirely separate issue, and would require major hackery to the array module (if you want the bits to be tightly packed, which I assume you do). Let's not mix it up with this.
--Guido van Rossum (home page: http://www.python.org/~guido/)

Guido van Rossum wrote:
def __repr__(self): if self: return "True" else: return "False" __str__ = __repr__
I don't like this: it will break too much code since there are already two singletons Py_True and Py_False available in Python and these return 1 / 0 resp.
But this is the whole point of introducing a new type rather than simply defining True as 1 and False as 0!
That's not how I read it: making bool a type would allow type checks to be done and this is a *much* more important feature to have than some different str(obj) output.
There are many situations when doing RPC or interfacing with other systems such as databases where a type check for booleans is needed.
Currently, this can be done by simply using the already existing Py_True and Py_False which are exposed at Python level through (1==1) and (1==0) and we should not break this scheme. '%s' % True must continue to deliver '0' otherwise you'll end up breaking interfaces which rely on this (such as database modules).
There's also another issue here: "True" and "False" are English words, "0" and "1" are language neutral.

But this is the whole point of introducing a new type rather than simply defining True as 1 and False as 0!
That's not how I read it: making bool a type would allow type checks to be done and this is a *much* more important feature to have than some different str(obj) output.
Depending on your POV, yes.
There are many situations when doing RPC or interfacing with other systems such as databases where a type check for booleans is needed.
Agreed, this is a nice additional advantage.
Currently, this can be done by simply using the already existing Py_True and Py_False which are exposed at Python level through (1==1) and (1==0) and we should not break this scheme. '%s' % True must continue to deliver '0' otherwise you'll end up breaking interfaces which rely on this (such as database modules).
That's a good question. Don't databases have a separate Boolean type? Is there really code out that relies on this? The code would have to assume that the boolean argument is already normalized to being exactly 0 or 1; a generalized Python truth value wouldn't work.
I can provide a real implementation next week, and we should have plenty of time to find out how much it breaks.
There's also another issue here: "True" and "False" are English words, "0" and "1" are language neutral.
Methinks you are getting desperate for arguments here. :-) Or should we also remove "if" from the language?
--Guido van Rossum (home page: http://www.python.org/~guido/)

Guido> Don't databases have a separate Boolean type?
So do, some don't. I'm pretty sure that MySQL (the only one I have any experience with) doesn't.
Skip

Skip> So do, some don't....
Try "Some do..."
Jeez, I am having an awful bout of typo-itis today! Must be that 60 degree weather we're blessed with in Chicago. Time to strap on the shoes and go for a run...
S

Guido van Rossum wrote:
But this is the whole point of introducing a new type rather than simply defining True as 1 and False as 0!
That's not how I read it: making bool a type would allow type checks to be done and this is a *much* more important feature to have than some different str(obj) output.
Depending on your POV, yes.
There are many situations when doing RPC or interfacing with other systems such as databases where a type check for booleans is needed.
Agreed, this is a nice additional advantage.
That's the main argument for adding a boolean *type* to the language. We already have the singletons...
Currently, this can be done by simply using the already existing Py_True and Py_False which are exposed at Python level through (1==1) and (1==0) and we should not break this scheme. '%s' % True must continue to deliver '0' otherwise you'll end up breaking interfaces which rely on this (such as database modules).
That's a good question. Don't databases have a separate Boolean type?
Yes and currently it is encouraged to use Py_True and Py_False on DB module output and the truth test on DB module input.
Is there really code out that relies on this?
mxODBC in SQL binding mode. Some databases only allow passing in strings, so mxODBC has to call str(obj) to pass the object stringified to the database.
This works just fine with Py_True and Py_False, since DBs know that 1 and 0 are true and false. I'm not sure how well 'True' and 'False' would work here, ODBC doesn't say anything on these values if used in the C API, in fact it doesn't have a native BOOLEAN type, just a BIT.
The code would have to assume that the boolean argument is already normalized to being exactly 0 or 1; a generalized Python truth value wouldn't work.
Right.
I can provide a real implementation next week, and we should have plenty of time to find out how much it breaks.
Perhaps you could clarify the need for these new __str__ and __repr__ values ?!
I'd be happy with repr(True) giving me 'True', but not str(True).
There's also another issue here: "True" and "False" are English words, "0" and "1" are language neutral.
Methinks you are getting desperate for arguments here. :-) Or should we also remove "if" from the language?
No. The point is that printing truth values up to now has always resulted in '0' or '1'. You are about to change that to 'True' and 'False'. This can create a l10n issue in existing applications.
It may also cause applications which write out boolean data this way to fail, e.g. report generation tools, XML generators, database extraction tools, etc... Just think of code like this:
print '<boolean value="%s">' % (x != 0)
(It's not like I'm running out of arguments :-)

That's the main argument for adding a boolean *type* to the language. We already have the singletons...
In C, not in Python!
mxODBC in SQL binding mode. Some databases only allow passing in strings, so mxODBC has to call str(obj) to pass the object stringified to the database.
This works just fine with Py_True and Py_False, since DBs know that 1 and 0 are true and false. I'm not sure how well 'True' and 'False' would work here, ODBC doesn't say anything on these values if used in the C API, in fact it doesn't have a native BOOLEAN type, just a BIT.
OK, so you may have to change one line in one module.
Perhaps you could clarify the need for these new __str__ and __repr__ values ?!
I'd be happy with repr(True) giving me 'True', but not str(True).
It just seems to make more sense if booleans print as True and False. But if that really is going to be the only place where things break, I'm willing to reconsider this.
No. The point is that printing truth values up to now has always resulted in '0' or '1'. You are about to change that to 'True' and 'False'. This can create a l10n issue in existing applications.
An application that prints the digits 0 or 1 to mean true or false doesn't sound very user-friendly to me either. I'm not worried that we'll get actual complaints from people that this broke their program.
It may also cause applications which write out boolean data this way to fail, e.g. report generation tools, XML generators, database extraction tools, etc... Just think of code like this:
print '<boolean value="%s">' % (x != 0)
(It's not like I'm running out of arguments :-)
We'll see. :-)
--Guido van Rossum (home page: http://www.python.org/~guido/)

Guido van Rossum wrote:
That's the main argument for adding a boolean *type* to the language. We already have the singletons...
In C, not in Python!
Sure we do:
True = (1==1) False = (1==0)
and many other modules and methods return these two singletons as well, so it's not like you are adding something new to the language :-)
mxODBC in SQL binding mode. Some databases only allow passing in strings, so mxODBC has to call str(obj) to pass the object stringified to the database.
This works just fine with Py_True and Py_False, since DBs know that 1 and 0 are true and false. I'm not sure how well 'True' and 'False' would work here, ODBC doesn't say anything on these values if used in the C API, in fact it doesn't have a native BOOLEAN type, just a BIT.
OK, so you may have to change one line in one module.
Nope. I'll have to add a new handler which detects the bool type and converts it to 1 or 0 resp.
The effort required to do this is not the argument, it's the fact that you are trying to break working code without any real life need. The PEP doesn't mention a single example where the advantage is so obvious that it requires breaking code.
Perhaps you could clarify the need for these new __str__ and __repr__ values ?!
I'd be happy with repr(True) giving me 'True', but not str(True).
It just seems to make more sense if booleans print as True and False. But if that really is going to be the only place where things break, I'm willing to reconsider this.
Good.
No. The point is that printing truth values up to now has always resulted in '0' or '1'. You are about to change that to 'True' and 'False'. This can create a l10n issue in existing applications.
An application that prints the digits 0 or 1 to mean true or false doesn't sound very user-friendly to me either. I'm not worried that we'll get actual complaints from people that this broke their program.
The problem is that the boolean output may not have been intended by the programmer. All he ever got was the integers 1 and 0 -- it was never obvious to the pure Python programmer that these two values were acutally the singletons Py_True and Py_False. Now you want to add additional semantics to those and things will look different on output.
It may also cause applications which write out boolean data this way to fail, e.g. report generation tools, XML generators, database extraction tools, etc... Just think of code like this:
print '<boolean value="%s">' % (x != 0)
(It's not like I'm running out of arguments :-)
We'll see. :-)

The effort required to do this is not the argument, it's the fact that you are trying to break working code without any real life need. The PEP doesn't mention a single example where the advantage is so obvious that it requires breaking code.
OK, now we're talking. You want more motivation. See my response to David Ascher; I'm going to add all that to the PEP online too.
I'd be happy with repr(True) giving me 'True', but not str(True).
It just seems to make more sense if booleans print as True and False. But if that really is going to be the only place where things break, I'm willing to reconsider this.
Good.
This is now in the PEP as an option.
The problem is that the boolean output may not have been intended by the programmer. All he ever got was the integers 1 and 0 -- it was never obvious to the pure Python programmer that these two values were acutally the singletons Py_True and Py_False. Now you want to add additional semantics to those and things will look different on output.
In the long run, you'll thank me for this.
--Guido van Rossum (home page: http://www.python.org/~guido/)

Hi,
Question: what will happen with all the return 1 or return 0 etc in the std lib and in user code and in the inline doc and docs?
(I have found 167 return 1 in the std lib and 176 return 0, and also code like this
if os.name == 'mac': # The macintosh will select a listening socket for # write if you let it. What might this mean? def writable (self): return not self.accepting else: def writable (self): return 1
which unchanged will define a bool vs int function.)
There are function in the std lib that return 1 on success, 0 on failure. Are there function that do the contrary like unix calls? Should these return True and False now. Maybe not? In distutil code I have seen at least one function documented as returning 'true' on success.
Then there are really predicate function/methods, they should probably be changed? but that means that the situation for the user will be *ideally* less muddy only when all the code uses True/False everytime it makes sense, and not 1/0.
regards.

Question: what will happen with all the return 1 or return 0 etc in the std lib and in user code and in the inline doc and docs?
Ideally they would have to be changed into True and False, but there's no hurry -- 0 and 1 will continue to be valid as truth values too.
(I have found 167 return 1 in the std lib and 176 return 0, and also code like this
if os.name == 'mac': # The macintosh will select a listening socket for # write if you let it. What might this mean? def writable (self): return not self.accepting else: def writable (self): return 1
which unchanged will define a bool vs int function.)
A job for PyChecker! :-)
There are function in the std lib that return 1 on success, 0 on failure. Are there function that do the contrary like unix calls? Should these return True and False now. Maybe not?
I doubt there are any functions returning 0 for success and -1 for failure, but if there are, they should not be changed.
In distutil code I have seen at least one function documented as returning 'true' on success.
Another reason to introduce a Boolean type. :-)
Then there are really predicate function/methods, they should probably be changed?
Yes. I hope that most of the C code goes through some easy choke point that makes it simple to change a lot of these at once (e.g. using Py_True and Py_False).
but that means that the situation for the user will be *ideally* less muddy only when all the code uses True/False everytime it makes sense, and not 1/0.
Yes, it will take time before everything is converted. That's why we must be careful to decide if we really want this.
--Guido van Rossum (home page: http://www.python.org/~guido/)

From: Guido van Rossum guido@python.org
but that means that the situation for the user will be *ideally* less muddy only when all the code uses True/False everytime it makes sense, and not 1/0.
Yes, it will take time before everything is converted. That's why we must be careful to decide if we really want this.
Yup, that's what I was thinking about. (Especially) During the conversion phase:
0 > 1
False
import baz bar = baz.Baz() bar.isfoo()
1
will be really less puzzling than
0 > 1
0
import baz bar = baz.Baz() bar.isfoo()
1
Or given that the usual truth semantics is still there, is just the first output "cosmetically" better /purer, and not really conceptually easier (?). I have no strong feeling about this, just wondering.
regards.

Guido van Rossum guido@python.org writes:
This PEP proposes the introduction of a new built-in type, bool, with two constants, False and True.
I would prefer these constants to be named "true" and "false", respectively.
Regards, Martin

I would prefer these constants to be named "true" and "false", respectively.
But all other built-in constants have an initial capital letter: None, NotImplemented, Ellipsis, ...
--Guido van Rossum (home page: http://www.python.org/~guido/)

Guido van Rossum wrote:
I would prefer these constants to be named "true" and "false", respectively.
But all other built-in constants have an initial capital letter: None, NotImplemented, Ellipsis, ...
True.
But this isn't as compelling as it might be, since None is the only one that enjoys common non-guru usage. It only counts as consistency if other people notice and remember the pattern.
The pattern people really care about is:
C99: true false C++: true false C#: true false Java: true false JavaScript: true false
(I can't find other case-sensitive languages with boolean types to compare.)
I also think repr(false) should return a randomly chosen line from an insults file. This makes the interactive prompt funnier:
1 == 1
true
1 == 17
LIAR!!!
## Jason Orendorff http://www.jorendorff.com/

C99: true false C++: true false C#: true false Java: true false JavaScript: true false
(I can't find other case-sensitive languages with boolean types to compare.)
Modula-2: TRUE FALSE
:-)
Greg Ewing, Computer Science Dept, +--------------------------------------+ University of Canterbury, | A citizen of NewZealandCorp, a | Christchurch, New Zealand | wholly-owned subsidiary of USA Inc. | greg@cosc.canterbury.ac.nz +--------------------------------------+

Greg Ewing wrote:
Jason Orendorff wrote:
C99: true false C++: true false C#: true false Java: true false JavaScript: true false
(I can't find other case-sensitive languages with boolean types to compare.)
Modula-2: TRUE FALSE
:-)
Indeed! But this is another argument in favor of "true" and "false", of course, because all Modula-2's keywords are UPPERCASE and all Python's keywords are lowercase. (Likewise, in VB All Keywords are Capitalized, so it makes sense to write True and False.)
## Jason Orendorff http://www.jorendorff.com/

"JO" == Jason Orendorff jason@jorendorff.com writes:
JO> Indeed! But this is another argument in favor of "true" and JO> "false", of course, because all Modula-2's keywords are JO> UPPERCASE and all Python's keywords are lowercase.
I've mostly tuned this thread out since I'm confident Guido will DTRT, but in case I've missed something, we aren't talking about making "true" and "false" (regardless of spelling) keywords, are we?
/me checks the PEP
Nope, and that's a very good thing, otherwise much code breakage will ensue.
In any event, I'm sure Guido's heard all the arguments by now and has made up his mind about this particular issue. For my money, True and False are just fine since they're singled objects sitting in builtins just like None and Ellipsis.
trying-to-find-the-right-channel-ly y'rs, -Barry

[Barry]
... In any event, I'm sure Guido's heard all the arguments by now and has made up his mind about this particular issue.
I expect you got the order backwards there <wink>, but this one isn't worth killing or dying for either way.
For my money, True and False are just fine since they're singled objects sitting in builtins just like None and Ellipsis.
Last I looked, everything in __builtin__ was an object ... None and Ellipsis are the only objects of their respective types, and maybe that's what "singled" means? If so, the same isn't true of True and False, unless they each get their own type too. Trying to come up with a "compelling" justification for the capitalization-- and either way --is doomed to sound silly to a critical ear.

"TP" == Tim Peters tim.one@comcast.net writes:
TP> [Barry] >> ... In any event, I'm sure Guido's heard all the arguments by >> now and has made up his mind about this particular issue.
TP> I expect you got the order backwards there <wink>, but this TP> one isn't worth killing or dying for either way.
:)
>> For my money, True and False are just fine since they're >> singled objects sitting in builtins just like None and >> Ellipsis.
TP> Last I looked, everything in __builtin__ was an object TP> ... None and Ellipsis are the only objects of their respective TP> types, and maybe that's what "singled" means? If so, the same TP> isn't true of True and False, unless they each get their own TP> type too. Trying to come up with a "compelling" justification TP> for the capitalization-- and either way --is doomed to sound TP> silly to a critical ear.
s/singled/singleton/
But yeah, when I design my own language it's gonna be TrUe and fAlSe, and you can bet that they'll have floating point values, because /everything/ in my language will have floating point values.
And it shall be called the...
truly-insane-machine-permuting-everything-that-ever-ran-slow-ly y'rs, -Barry

Guido van Rossum guido@python.org writes:
I would prefer these constants to be named "true" and "false", respectively.
But all other built-in constants have an initial capital letter: None, NotImplemented, Ellipsis, ...
That certainly doesn't apply generally to all of Python: sys.version, sys.byteorder, sys.platform, sys.maxunicode, string.digits, string.other_constant_strings.
Those you bring up are conceptually "objects", in the sense that you want to be aware of identity, whereas true and false are conceptually "values", in the sense that you never care about their identity, only about their state.
Regards, Martin

martin@v.loewis.de (Martin v. Loewis):
But all other built-in constants have an initial capital letter: None, NotImplemented, Ellipsis, ...
Those you bring up are conceptually "objects", in the sense that you want to be aware of identity, whereas true and false are conceptually "values", in the sense that you never care about their identity, only about their state.
But the PEP explicitly defines them as singletons, so that you *can* rely on identity if you want. On that basis, they should have capital-letter names.
Greg Ewing, Computer Science Dept, +--------------------------------------+ University of Canterbury, | A citizen of NewZealandCorp, a | Christchurch, New Zealand | wholly-owned subsidiary of USA Inc. | greg@cosc.canterbury.ac.nz +--------------------------------------+

----- Original Message ----- From: "Martin v. Loewis" martin@v.loewis.de To: "Guido van Rossum" guido@python.org Cc: python-dev@python.org Sent: Friday, March 08, 2002 12:51 PM Subject: Re: [Python-Dev] For review: PEP 285: Adding a bool type
Guido van Rossum guido@python.org writes:
This PEP proposes the introduction of a new built-in type, bool, with two constants, False and True.
I would prefer these constants to be named "true" and "false", respectively.
Don't you think using "true" in place of "False" and "false" in place of "True" is bound to cause a little controversy <0.7wink>?
respectively yours, Dave

Current Rationale for PEP 285:
Most languages eventually grow a Boolean type; even C99 has one. It's useful to be able to tell from a function result that the outcome has Boolean semantics, and it helps with things like RPC protocols that may prefer to encode Booleans differently from integers.
I'd like to get a clearer understanding of the rationale of adding a new type which would become commonly used, in view of the cost of the change (in terms of complexity, backwards compatibility issues, development/debugging time, outdated docs, etc.).
I think it's key to identify the ways in which the current semantics and idioms are suboptimal.
1) "Most languages eventually grow a Boolean type; even C99 has one."
While I've often wanted a boolean (mostly for 'aesthetic reasons'), I think it's important that the rationale for a language modification be deeper than "everyone else does it".
2) "it helps with things like RPC protocols that may prefer to encode Booleans differently from integers."
That is a real issue except that it seems to have been solved relatively well by all of the language bindings so far. IIRC, there are some awkward situations in Jython if you explicitly want to send a boolean to a polymorphic function, but that's an edge case.
3) "It's useful to be able to tell from a function result that the outcome has Boolean semantics"
This is intriguing. I can't think of a case where the current integer return values have caused me problems or concerns that weren't solved by simply understanding what the function was about. What use case did you have in mind?
4) Booleans lead quickly to the 'memory savings' notions of packed arrays of bits, which seems a detail of array implementation issues different from this proposal. I think the array folks could implement this w/o a "core" Python datatype, just like they/we've dealt with low-precision floats.
All in all, I'm neither for nor against at this point, but I think the rationale for the change needs further elaboration. And feeling conservative today, without that I'd vote against it on complexity grounds.
--david

Current Rationale for PEP 285:
Most languages eventually grow a Boolean type; even C99 has one. It's useful to be able to tell from a function result that the outcome has Boolean semantics, and it helps with things like RPC protocols that may prefer to encode Booleans differently from integers.
I'd like to get a clearer understanding of the rationale of adding a new type which would become commonly used, in view of the cost of the change (in terms of complexity, backwards compatibility issues, development/debugging time, outdated docs, etc.).
Yeah, there's always a lot of things that must be changed...
Most Python documentation currently contains some sort of apology for the fact that there's no separate Boolean type, so at least the change in the docs would be a positive one.
I think it's key to identify the ways in which the current semantics and idioms are suboptimal.
- "Most languages eventually grow a Boolean type; even C99 has one."
While I've often wanted a boolean (mostly for 'aesthetic reasons'), I think it's important that the rationale for a language modification be deeper than "everyone else does it".
It is commonly seen as a small wart. While the wart is easy to work around (I've seen lots of code defining constants True and False or variations), what's missing is a standard way so everybody can do it the same way.
- "it helps with things like RPC protocols that may prefer to encode
Booleans differently from integers."
That is a real issue except that it seems to have been solved relatively well by all of the language bindings so far. IIRC, there are some awkward situations in Jython if you explicitly want to send a boolean to a polymorphic function, but that's an edge case.
I didn't invent this argument; Marc-Andre thought it would be helpful. I see it as a mild argument at most. But it's useful that in situations where a receiver would like to distinguish Booleans from ints, you can now do it.
- "It's useful to be able to tell from a function result that the outcome has Boolean semantics"
This is intriguing. I can't think of a case where the current integer return values have caused me problems or concerns that weren't solved by simply understanding what the function was about. What use case did you have in mind?
When showing people comparison operators etc. in the interactive shell, I think this is a tad ugly:
>>> a = 13 >>> b = 12 >>> a > b 1 >>>
If this was:
>>> a > b True >>>
it would require one millisecond less thinking.
There's also the issue (which I've seen puzzling even experienced Pythonistas who had been away from the language for a while) that if you see:
>>> cmp(a, b) 1 >>> cmp(a, a) 0 >>>
you might be tempted to believe that cmp() also returned a truth value. If ints are not (normally) used for Booleans results, this would stand out much more clearly as something completely different.
- Booleans lead quickly to the 'memory savings' notions of packed
arrays of bits, which seems a detail of array implementation issues different from this proposal. I think the array folks could implement this w/o a "core" Python datatype, just like they/we've dealt with low-precision floats.
This doesn't interest me much.
All in all, I'm neither for nor against at this point, but I think the rationale for the change needs further elaboration. And feeling conservative today, without that I'd vote against it on complexity grounds.
Wait till you've seen the implementation. :-)
--Guido van Rossum (home page: http://www.python.org/~guido/)

Just found another argument:
Guido van Rossum wrote:
When showing people comparison operators etc. in the interactive shell, I think this is a tad ugly:
>>> a = 13 >>> b = 12 >>> a > b 1 >>>
If this was:
>>> a > b True >>>
it would require one millisecond less thinking.
and then they do:
(a > b) * 10
10
or
True * 10
10
False * 10
0
If you want to dive into logic here, the only correct output would be:
True * 10
True
False * 10
False
However, this would break even more code... your bool type is much more like a bit type (or would have to behave like one in order to maintain backwards compatibility).

True * 10
10
False * 10
0
If you want to dive into logic here, the only correct output would be:
True * 10
True
False * 10
False
What has logic got to do with this?
However, this would break even more code... your bool type is much more like a bit type (or would have to behave like one in order to maintain backwards compatibility).
I never said otherwise. It behaves exactly like int except for those operations where the PEP specifies something different. This is intentional, since anything else will break too much code.
--Guido van Rossum (home page: http://www.python.org/~guido/)

Guido van Rossum wrote:
True * 10
10
False * 10
0
If you want to dive into logic here, the only correct output would be:
True * 10
True
False * 10
False
What has logic got to do with this?
Booleans are by nature truth values. You can do boolean algebra on them, but this algebra is completly different from what you get if you treat them as numbers having two values 0 and 1 (bits). Booleans representing a logical value should not implement +, -, *, etc. at all. Instead, they would have to be converted to integers first, to implement these operations.
I think in summary, the confusion we have run into here is caused by Python's use of bits to represent booleans. You would like to move this usage more in the direction of booleans, but only half way.
However, this would break even more code... your bool type is much more like a bit type (or would have to behave like one in order to maintain backwards compatibility).
I never said otherwise. It behaves exactly like int except for those operations where the PEP specifies something different. This is intentional, since anything else will break too much code.
Exactly; which is why I don't understand the move to override __str__ with something which doesn't have anything to do with integers :-)
Heck, it's only one method we're argueing about here. Why are all these cycles needed to convince you that backwards compatibility is better than the cosmetics of having str(True) return 'True' ? You can always implement the latter as a subtype of bool if you care enough and without breaking code.

[MAL]
If you want to dive into logic here, the only correct output would be:
True * 10
True
False * 10
False
[Guido]
What has logic got to do with this?
[MAL]
Booleans are by nature truth values. You can do boolean algebra on them, but this algebra is completly different from what you get if you treat them as numbers having two values 0 and 1 (bits). Booleans representing a logical value should not implement +, -, *, etc. at all. Instead, they would have to be converted to integers first, to implement these operations.
So you're reversing your position. First (see above) you were pleading that True*10 should yield True. Now you are pleading that it should raise an exception.
Anyway, in a brand new language the latter might be a good idea, but since we're trying to evolve Python without breaking (much) existing code, we have no choice: bools must behave like ints as much as possible, especially in arithmetic.
I think in summary, the confusion we have run into here is caused by Python's use of bits to represent booleans.
I don't understand this. The way I see it, current Python doesn't use bits for Booleans. It has no Boolean type, and the integers 0 and 1 are conventional but not the only ways to spell Boolean outcomes.
You would like to move this usage more in the direction of booleans, but only half way.
Yes, forced by backwards compatibility.
Exactly; which is why I don't understand the move to override __str__ with something which doesn't have anything to do with integers :-)
Probably because we have a different intuition on how str() is used. For me, it's mostly used as an output conversion. But it seems that for you, conversion to a decimal int is important because you need to feed that into other applications that require decimal strings.
Heck, it's only one method we're argueing about here. Why are all these cycles needed to convince you that backwards compatibility is better than the cosmetics of having str(True) return 'True' ?
Maybe because at the start it wasn't clear that that is your only *real* objection, and you brought so many other arguments into play? Or maybe because you and I are using Python in very different ways, so that what's obvious for you isn't always obvious for me (and vice versa)?
You can always implement the latter as a subtype of bool if you care enough and without breaking code.
I thought about this last night, and realized that you shouldn't be allowed to subclass bool at all! A subclass would only be useful when it has instances, but the mere existance of an instance of a subclass of bool would break the invariant that True and False are the only instances of bool! (An instance of a subclass of C is also an instance of C.) I think it's important not to provide a backdoor to create additional bool instances, so I think bool should not be subclassable.
Of course, you can define your own subclass of int similar to the bool class I show in the PEP, and you can give it any semantics you want -- but that would also defeat the purpose of having a standard bool.
What will happen in reality is that people will have to write:
print repr(b)
rather than:
print b
That's not terribly bad. But I'm not sure I'm ready to answer the complaints from newbies who are confused by this:
>>> isinstance(1, int) True >>> print isinstance(1, int) 1 >>>
So I need someone else to chime in with additional evidence that str(True) should be '1', not 'True'. So far you've been carrying this particular argument all by yourself.
--Guido van Rossum (home page: http://www.python.org/~guido/)

Hi. [after contemplation of scheme, CL, and Python]
That's not terribly bad. But I'm not sure I'm ready to answer the complaints from newbies who are confused by this:
>>> isinstance(1, int) True >>> print isinstance(1, int) 1 >>>
My 2cts. IMHO an explicit bool type add cognitive burden, does not subtract from there, especially given that Python should preserve its truth semantics rules.
The only win is that we have a blessed return type for predicates, which is just an ideal win as long as there is code around that does not stick with the new convention. Ant the cometics.
A more clear win is RPC (but so late in the game it seems people have dealt with that otherwise).
So it seems it is a matter of BDFL's taste :). By the way the proposal open new style questions: E.g. Should one write:
[A] def f(arg,optflag=0):
f(...,1)
Or
[B] def f(arg,optflag=False):
f(...,True).
Guido is up to your taste :).
regards, Samuele Pedroni.

Guido van Rossum wrote:
[MAL]
If you want to dive into logic here, the only correct output would be:
> True * 10
True
> False * 10
False
[Guido]
What has logic got to do with this?
[MAL]
Booleans are by nature truth values. You can do boolean algebra on them, but this algebra is completly different from what you get if you treat them as numbers having two values 0 and 1 (bits). Booleans representing a logical value should not implement +, -, *, etc. at all. Instead, they would have to be converted to integers first, to implement these operations.
So you're reversing your position. First (see above) you were pleading that True*10 should yield True. Now you are pleading that it should raise an exception.
No, I'm just giving evidence of what mixing booleans with bits can lead to.
Anyway, in a brand new language the latter might be a good idea, but since we're trying to evolve Python without breaking (much) existing code, we have no choice: bools must behave like ints as much as possible, especially in arithmetic.
Right, but please don't try to add some booleaness to bits.
I think in summary, the confusion we have run into here is caused by Python's use of bits to represent booleans.
I don't understand this. The way I see it, current Python doesn't use bits for Booleans. It has no Boolean type, and the integers 0 and 1 are conventional but not the only ways to spell Boolean outcomes.
Bits are 1 and 0. Booleans are True and False. You can coerce the two mathematical types, but they essentially cover different areas, e.g.
True - True
False
simply doesn't fly.
You would like to move this usage more in the direction of booleans, but only half way.
Yes, forced by backwards compatibility.
Exactly; which is why I don't understand the move to override __str__ with something which doesn't have anything to do with integers :-)
Probably because we have a different intuition on how str() is used. For me, it's mostly used as an output conversion. But it seems that for you, conversion to a decimal int is important because you need to feed that into other applications that require decimal strings.
Right.
Heck, it's only one method we're argueing about here. Why are all these cycles needed to convince you that backwards compatibility is better than the cosmetics of having str(True) return 'True' ?
Maybe because at the start it wasn't clear that that is your only *real* objection, and you brought so many other arguments into play?
You started this game and asked for these many arguments :-)
My only objection is overriding the __str__ method. Everything else is just fine.
You don't have a boolean type in the sense of algebra, but we can't change that due to Python's history and a true algebraic boolean type can easily be written as extension, so it doesn't worry me much.
Hmm, perhaps you should name the type "truth" or "truthvalue" rather than boolean.
Or maybe because you and I are using Python in very different ways, so that what's obvious for you isn't always obvious for me (and vice versa)?
Could be... I don't like it when things are broken on purpose just to have an interactive session return "nice" output. I also don't like scanning tons of code to find the few instances where this change breaks application interop.
There must be other ways to satisfy your requirements and mine.
You can always implement the latter as a subtype of bool if you care enough and without breaking code.
I thought about this last night, and realized that you shouldn't be allowed to subclass bool at all! A subclass would only be useful when it has instances, but the mere existance of an instance of a subclass of bool would break the invariant that True and False are the only instances of bool! (An instance of a subclass of C is also an instance of C.) I think it's important not to provide a backdoor to create additional bool instances, so I think bool should not be subclassable.
Of course, you can define your own subclass of int similar to the bool class I show in the PEP, and you can give it any semantics you want -- but that would also defeat the purpose of having a standard bool.
What will happen in reality is that people will have to write:
print repr(b)
rather than:
print b
That's not terribly bad. But I'm not sure I'm ready to answer the complaints from newbies who are confused by this:
>>> isinstance(1, int) True >>> print isinstance(1, int) 1 >>>
This is not different from printing other objects:
from mx.DateTime import * now()
<DateTime object for '2002-03-09 18:32:10.21' at 82424b8>
print now()
2002-03-09 18:32:12.93
or
1.4
1.3999999999999999
print 1.4
1.4
So I need someone else to chime in with additional evidence that str(True) should be '1', not 'True'. So far you've been carrying this particular argument all by yourself.
I was also the only one that had objections when nested scopes were first proposed by Jeremy on this list... I'm sure others will chime in once you have checked in an implementation.

On 9 Mar 2002 at 18:44, M.-A. Lemburg wrote:
Guido van Rossum wrote:
So far you've been carrying this particular argument all by yourself.
I was also the only one that had objections when nested scopes were first proposed by Jeremy on this list... I'm sure others will chime in once you have checked in an implementation.
It hasn't helped that the argument has contained a whole lot of red herrings.
Personally, I think repr(True) should return 1 and str(True) should return "True" (in line with str being the "friendly" and repr the "techy" representations).
If there were any proposal for and / or to return booleans, I'd scream bloody murder, but in my own code, I don't forsee much breakage otherwise.
-- Gordon http://www.mcmillan-inc.com/

On 9 Mar 2002 at 19:14, Samuele Pedroni wrote:
eval(repr(True)) is True
should be true.
You're right. I confused myself by thinking a 1 would generally do where a True was expected.
-- Gordon http://www.mcmillan-inc.com/

Gordon McMillan wrote:
On 9 Mar 2002 at 18:44, M.-A. Lemburg wrote:
Guido van Rossum wrote:
So far you've been carrying this particular argument all by yourself.
I was also the only one that had objections when nested scopes were first proposed by Jeremy on this list... I'm sure others will chime in once you have checked in an implementation.
It hasn't helped that the argument has contained a whole lot of red herrings.
While I don't agree that the arguments I included in the thread were red herrings, I do admit that this was sports; Guido started the game and I played along ;-)
Personally, I think repr(True) should return 1 and str(True) should return "True" (in line with str being the "friendly" and repr the "techy" representations).
If there were any proposal for and / or to return booleans, I'd scream bloody murder, but in my own code, I don't forsee much breakage otherwise.
I like the fact that we add extra meta-information to Py_True and Py_False (type information in this case).
However, we should not pretend the type implements something which it doesn't. It certainly does not implement boolean algebra so the name is misleading.
Making it a true boolean type would cause too much breakage though, so I'd rather have it become an abstract type, i.e. no special casing except maybe fixing __repr__ to indicate the different type to the user...
+1 on making bool an abstract subtype of integers and having Py_True and Py_False as only instances
-1 on overriding interfaces other than informational ones such as __repr__

From: M.-A. Lemburg mal@lemburg.com
+1 on making bool an abstract subtype of integers and having Py_True and Py_False as only instances
-1 on overriding interfaces other than informational ones such as __repr__
So you mean just:
class truth(int): # other names?, should not be subclassable def __new__(cls,val): # ?? if val: return true else: return false def __repr__(self): if self: return 'true' else: return 'false'
true = int.__new__(truth,1) # also Py_True false = int.__new__(truth,0) # also Py_False

You started this game and asked for these many arguments :-)
OK, I've played enough. :-)
My only objection is overriding the __str__ method. Everything else is just fine.
Good.
You don't have a boolean type in the sense of algebra, but we can't change that due to Python's history and a true algebraic boolean type can easily be written as extension, so it doesn't worry me much.
Agreed. There's only so much we can do without applying the time machine to 12 years of code developed by 100,000s of people.
Hmm, perhaps you should name the type "truth" or "truthvalue" rather than boolean.
Yuck. It's called bool (or Boolean) everywhere else, even when the semantics are defined to be just different names for 0 and 1. I don't like to innovate here.
Could be... I don't like it when things are broken on purpose just to have an interactive session return "nice" output. I also don't like scanning tons of code to find the few instances where this change breaks application interop.
There must be other ways to satisfy your requirements and mine.
We'll see. I'm flexible.
--Guido van Rossum (home page: http://www.python.org/~guido/)

I've spent an evening hacking. There's now an experimental implementation of the PEP on SourceForge:
http://sourceforge.net/tracker/?func=detail&atid=305470&aid=528022&a...
It including a unittest file, test_bool.py, which checks the promises made in the PEP, and a little bit of documentation. (Unfortunately, because much about new-style classes in 2.2 is not yet documented, documenting bool as a subclass of int sticks out like a sore thumb. :-)
With this, about 12 tests fail for me (on Linux); I'll look into these later. They appear shallow (mostly doctests dying on True or False where 1 or 0 was expected).
Note: this patch does not mean that the PEP is accepted -- it just means that a sample implementation exists in case someone wants to explore the effects of the PEP on their code.
It should be easy for example to create a variant that makes str(False) == "0" rather than "False"; if I do that, 4 more test succeed. Changing "False" into "false" would be slightly more work, because it turns out that the names of the truth values occurs frequently in doc strings (and I updated all the ones I could find that were affected).
--Guido van Rossum (home page: http://www.python.org/~guido/)

[GvR]
I've spent an evening hacking. There's now an experimental implementation of the PEP on SourceForge:
http://sourceforge.net/tracker/?func=detail&atid=305470&aid=528022&a... 0
It including a unittest file, test_bool.py, which checks the promises made in the PEP, and a little bit of documentation. (Unfortunately, because much about new-style classes in 2.2 is not yet documented, documenting bool as a subclass of int sticks out like a sore thumb. :-)
(This is a serious question) How do you imagine bool presented to (non-programmer) newbies.
Not presented. Presented disjunct from int at the beginning. Using the notion of subtyping/subclassing. Operationally: True == 1 False == 0 etc .
Thanks. Samuele Pedroni.

(This is a serious question) How do you imagine bool presented to (non-programmer) newbies.
Not presented. Presented disjunct from int at the beginning. Using the notion of subtyping/subclassing. Operationally: True == 1 False == 0 etc .
Good point. The tutorial needs to be updated. I propose not to make a big deal from it, but to mention that (a) you get bools from most propositions, (b) False==0, True==1, (c) most other objects are also usable as Boolean values, e.g. "" is false, "x" is true. Needs to distinguish clearly between False and True (the specific bool values) and more general falsehood/truth.
--Guido van Rossum (home page: http://www.python.org/~guido/)

Guido van Rossum writes:
(Unfortunately, because much about new-style classes in 2.2 is not yet documented, documenting bool as a subclass of int sticks out like a sore thumb. :-)
So? Document it. That will lead to questions to python-docs and bug reports on SourceForge, which lead to improvements in the docs.
-Fred

It is commonly seen as a small wart. While the wart is easy to work around (I've seen lots of code defining constants True and False or variations), what's missing is a standard way so everybody can do it the same way.
That's easy. That problem can be dealt with by defining True and False as built-in constants with values 1 and 0 respectively (while you're at it, make None read-only =).
- "it helps with things like RPC protocols that may prefer to encode
Booleans differently from integers."
That is a real issue except that it seems to have been solved relatively well by all of the language bindings so far. IIRC, there are some awkward situations in Jython if you explicitly want to send a boolean to a polymorphic function, but that's an edge case.
I didn't invent this argument; Marc-Andre thought it would be helpful. I see it as a mild argument at most. But it's useful that in situations where a receiver would like to distinguish Booleans from ints, you can now do it.
Agreed. I also agree w/ the mildness of it.
- "It's useful to be able to tell from a function result that the outcome has Boolean semantics"
This is intriguing. I can't think of a case where the current integer return values have caused me problems or concerns that weren't solved by simply understanding what the function was about. What use case did you have in mind?
When showing people comparison operators etc. in the interactive
>>> a > b 1
vs.
>>> a > b True
and:
>>> cmp(a, b) 1 >>> cmp(a, a) 0
Which really seems to be the key issue, both as a positive (your argument) and as a negative (MAL's posts).
I wonder if the str()/repr() distinction or % formatting codes could help break the logjam. Probably not.
I'm still not convinced that the disease is worth the cure, but I'm open-minded =).
--david

That's easy. That problem can be dealt with by defining True and False as built-in constants with values 1 and 0 respectively (while you're at it, make None read-only =).
If PEP 285 is withdrawn, I could do a milder version.
When showing people comparison operators etc. in the interactive
>>> a > b 1
vs.
>>> a > b True
and:
>>> cmp(a, b) 1 >>> cmp(a, a) 0
Which really seems to be the key issue, both as a positive (your argument) and as a negative (MAL's posts).
It certainly is what motivates me.
I wonder if the str()/repr() distinction or % formatting codes could help break the logjam. Probably not.
Marc-Andre has suggested that, and I'm willing to give it a try if it's needed to save the PEP.
I'm still not convinced that the disease is worth the cure, but I'm open-minded =).
:-)
Now let's you and I go decide on the Python track and tutorials for OSCON 2002...
--Guido van Rossum (home page: http://www.python.org/~guido/)

On Fri, 8 Mar 2002, Guido van Rossum wrote:
Now let's you and I go decide on the Python track and tutorials for OSCON 2002...
I know the deadlines was a week ago, but I just found out (about 10 minutes ago) that I will be in the country for OSCON 2002. Is it too late to volunteer to do a Python metaclass and new-object model tutorial?
-Kevin
-- Kevin Jacobs The OPAL Group - Enterprise Systems Architect Voice: (216) 986-0710 x 19 E-mail: jacobs@theopalgroup.com Fax: (216) 986-0714 WWW: http://www.theopalgroup.com

----- Original Message ----- From: "David Ascher" DavidA@ActiveState.com
I wonder if the str()/repr() distinction or % formatting codes could help break the logjam. Probably not.
I'm still not convinced that the disease is worth the cure, but I'm open-minded =).
The big reason I was excited about bool in C++ when we got it was that I knew I'd be able to do this, given b1,b2 of type bool:
if (b1 == b2) ...
And there would be no chance of getting the wrong result because b1 and b2 were different ways to spell "true" (i.e. b1 == 1, b2 == 42). I guess the python analogy would be:
if bool(x[y]) == bool(z): ...
or something like that.
FWIW, Dave

Guido,
I'm kinda curious. I understand all the arguments, but they've been around for a long time. It's not like any of the reasons for having a boolean are new. What straw broke your pet camel's back and made you sit down and say to yourself, "We need a boolean type in Python. I think I'll write a PEP today instead of going to Starbucks for a latte."?
Skip

I'm kinda curious. I understand all the arguments, but they've been around for a long time. It's not like any of the reasons for having a boolean are new. What straw broke your pet camel's back and made you sit down and say to yourself, "We need a boolean type in Python. I think I'll write a PEP today instead of going to Starbucks for a latte."?
Well, the subclassing from int solution is new in 2.2. Other than that, I was thinking of something non-controversial to be added to 2.3. Big mistake... :-)
Time for my latte.
--Guido van Rossum (home page: http://www.python.org/~guido/)

[Skip Montanaro]
I'm kinda curious. I understand all the arguments, but they've been around for a long time. It's not like any of the reasons for having a boolean are new. What straw broke your pet camel's back and made you sit down and say to yourself, "We need a boolean type in Python. I think I'll write a PEP today instead of going to Starbucks for a latte."?
It's obvious to me. I sent a "PEP Parade" message last night, stating in part that Guido wanted to keep new features out of the core for 2.3. Guido simply couldn't let a chance to prove me wrong slip by; indeed, that was my intent in making the claim to begin with <wink>.

[Guido]
... (I've seen lots of code defining constants True and False or variations), what's missing is a standard way so everybody can do it the same way.
That's what drove C99 to standardize a bool type. Indeed, Python may be the only non-trivial C project I've worked on that didn't #define its own boolean gimmick for internal use.
I'd like to note too that a Boolean concept is needed all over the place, despite that it's not an official type. It shows up in docstrings even now:
print hasattr.__doc__
hasattr(object, name) -> Boolean ...
import os print os.isatty.__doc__
isatty(fd) -> Boolean ...
That's not an exhaustive list, just a tease.

I've been mulling over the whole Boolean issue and up till now it's been bothering me vaguely but i haven't been able to put my finger on it. I think i have an idea now what's bugging me, though.
I've generated an outline summary at http://lfw.org/python/bool if you'd like to see an overview of this thread.
In my mind, the current thinking is something like this:
There are many false values (0, None, [], (), '', {}, instances that have len() = 0, and so on). Other values are true.
The general convention is that each type has one false value, and that it corresponds to a zero magnitude or an empty container. For types where + makes sense, usually x + <the false value> = x.
It is often the case that integers are convenient to work with, so in the absence of any reason to choose any other particular type, people typically use 0 and 1.
This is not so bad, and not difficult to explain.
But in the new scheme, there is a "blessed" Boolean type. Does this make the other kinds of true and false less legitimate? If so, then what are we to do with them? If not, then when is it more correct to use Boolean values?
I guess this is really an issue of where we are going with this. I know that right now the proposal is designed for compatibility, but i'd like to know what eventual goal state Guido has in mind. (Let's call this lim_{n -> inf} Python n, or Python inf for short.)
Q1. In Python inf, will "if" and "while" require a Boolean expression?
Q2. In Python inf, will "and", "or", "not" require Boolean operands?
Q3. In Python inf, will "True + 2" raise a TypeError?
If the answer to Q1 is "yes", then people won't be able to write
if list:
any more. Instead people will write one of these:
if list != []: if len(list) != 0: if len(list) > 0:
which is troublesome (a) because there's more to type and read; (b) because there are now many ways to write the same thing, instead of one simple way; and (c) because it makes the code less generic (the first option will fail if i replace "list" with some container that i want to test for emptiness).
If the answer to Q1 is "no", then i don't see when people will want to use Boolean values at all. Booleans and integers will remain interchangeable in many contexts, which leads to ambiguity. When we read code, we won't be sure whether Booleans are involved or not, and when we edit it we want to be consistent, but won't know whether to write in the Boolean style or the 0/1 style.
Will people waste time on silly arguments about "thou shalt change thy code to the One True/False Style, because it is the Proper Way" vs. "but 0/1 works and it's less typing and i don't want to bother"? Will programmers expend a bunch of effort editing their code to work the new way -- effort that could have been better spent fixing and improving their programs? (Instantiate the preceding question with programmers := Python-developers and programs := Python standard library.)
-- ?!ng

Ka-Ping Yee wrote:
Will people waste time on silly arguments about "thou shalt change thy code to the One True/False Style, because it is the Proper Way" vs. "but 0/1 works and it's less typing and i don't want to bother"? Will programmers expend a bunch of effort editing their code to work the new way -- effort that could have been better spent fixing and improving their programs?
Good point. This reminds me of the unofficial deprecation of string exceptions. I still find using string exceptions is darn convenient. Just adding 'import exceptions' is enough of a step to stop me from doing it 'right' until the program has scaled up enough (usually the same point where top-level functions become methods on a new class =).
--david

"DA" == David Ascher DavidA@ActiveState.com writes:
DA> Good point. This reminds me of the unofficial deprecation of DA> string exceptions. I still find using string exceptions is DA> darn convenient. Just adding 'import exceptions' is enough of DA> a step to stop me from doing it 'right' until the program has DA> scaled up enough (usually the same point where top-level DA> functions become methods on a new class =).
Why do you have to import exceptions? All the exception classes in exceptions are already builtins. Is
class MyEXC(Exception): pass
really any more typing than
MyEXC = 'My Exception'
(expecially given that the base class specification isn't even necessary)?
-Barry

david wrote:
Good point. This reminds me of the unofficial deprecation of string exceptions. I still find using string exceptions is darn convenient. Just adding 'import exceptions' is enough of a step to stop me from doing it 'right'
umm. why would you ever need to do that?
dir(__builtins__)
['ArithmeticError', ...]
import exceptions dir(exceptions)
['ArithmeticError', ...]
for name in dir(exceptions):
... if getattr(__builtins__, name, None) == None: ... print name, "is missing" ...
and if you don't want to, you don't have to inherit from the Exception class either. the difference between
MyException = "MyException"
and
class MyException: pass
isn't really that big...
</F>

From: Ka-Ping Yee ping@lfw.org
Will people waste time on silly arguments about "thou shalt change thy code to the One True/False Style, because it is the Proper Way" vs. "but 0/1 works and it's less typing and i don't want to bother"? Will programmers expend a bunch of effort editing their code to work the new way -- effort that could have been better spent fixing and improving their programs? (Instantiate the preceding question with programmers := Python-developers and programs := Python standard library.)
Although it was not said so explicitly, my design exercise related to Jython shows that probably a lot of Jython user code will still preserve many:
jbean.beanProp = 1
where 1 would be better written as True.
regards.

Oops, silly me!
From: Samuele Pedroni pedroni@inf.ethz.ch
Although it was not said so explicitly, my design exercise related to Jython shows that probably a lot of Jython user code will still preserve many:
jbean.beanProp = 1
where 1 would be better written as True.
Obvisiouly the same problem exists for the flags in the all pre-exiting Python code, and all the = 0 = 1 there. And it seems Guido does not care about that.
regards.

Ka-Ping Yee ping@lfw.org:
But in the new scheme, there is a "blessed" Boolean type. Does this make the other kinds of true and false less legitimate?
No, in the sense that they will still work in boolean contexts. Yes, in the sense that there will now be a "real" boolean type, which is perhaps best thought of as the *only* boolean type, with other values being converted to booleans in certain contexts.
If not, then when is it more correct to use Boolean values?
When what you're representing is purely a boolean and nothing else. Just ask yourself "If I were writing this in Pascal (or some other language with a strong boolean type) would I declare it as a boolean?" The answer to that should be pretty clear in most cases.
Greg Ewing, Computer Science Dept, +--------------------------------------+ University of Canterbury, | A citizen of NewZealandCorp, a | Christchurch, New Zealand | wholly-owned subsidiary of USA Inc. | greg@cosc.canterbury.ac.nz +--------------------------------------+

Greg Ewing wrote:
Ka-Ping Yee ping@lfw.org:
But in the new scheme, there is a "blessed" Boolean type. Does this make the other kinds of true and false less legitimate?
These "other kinds of true and false" should IMHO be implemented via a conversion method __bool__ (just like __int__, __str__, __unicode__ etc.) and will be a bool aware version of __nonzero__ which should be deprecated.
if should internally call this bool conversion method.
Bye, Walter Dörwald

These "other kinds of true and false" should IMHO be implemented via a conversion method __bool__ (just like __int__, __str__, __unicode__ etc.) and will be a bool aware version of __nonzero__ which should be deprecated.
if should internally call this bool conversion method.
IMO there's no need to have a separate __bool__. We can simply say __nonzero__ may return 0 or False, or 1 or True. I see no advantage in introducing a separate __bool__.
--Guido van Rossum (home page: http://www.python.org/~guido/)
participants (19)
-
aahz@rahul.net
-
barry@zope.com
-
David Abrahams
-
David Ascher
-
Fred L. Drake, Jr.
-
Fredrik Lundh
-
Gordon McMillan
-
Greg Ewing
-
Guido van Rossum
-
Jason Orendorff
-
Ka-Ping Yee
-
Kevin Jacobs
-
M.-A. Lemburg
-
martin@v.loewis.de
-
Neil Schemenauer
-
Samuele Pedroni
-
Skip Montanaro
-
Tim Peters
-
Walter Dörwald