while true: !!!

Alex Martelli aleaxit at yahoo.com
Tue Dec 19 11:50:20 EST 2000


"Marcin 'Qrczak' Kowalczyk" <qrczak at knm.org.pl> wrote in message
news:slrn93st0m.6c1.qrczak at qrnik.zagroda...
> Mon, 18 Dec 2000 17:05:51 +0100, Alex Martelli <aleaxit at yahoo.com> pisze:
>
> > I think it would be inconsistent, un-Pythonic, to add a
> > fundamental type for 'conceptual' reasons, without any
> > practical, measurable benefit.  For example, Python does
> > away with the distinction between 'a character' and 'a
> > string of length 1' -- a distinction that is religiously
> > maintained in C, Pascal, Java, etc,
>
> OTOH Python does not equate characters with integers. C, C++ and Java
> do.

Wrong!  C's types are always slightly fuzzy, but that does
NOT apply to C++ or Java; e.g., in C++:

void f(int) {
    cout << 'integer\n';
}

void f(char) {
    cout << 'character\n';
}

There is no 'equate' between the char[acter] and the int[eger]
case: if you call
    f('7')
you will see 'character' on standard output, while if you
call
    f(7)
you will see 'integer'.

A character can be _implicitly *coerced*_ to other types,
but that is very different from 'equating': the distinction
is perfectly sharp, just as, say, between a char* and a
const char*, even if the first can be coerced to the
second just as implicitly.


Python does implicit coercion between number types, to
string in a few contexts (e.g., a print statement), and
between sequence types in a few other contexts -- and
that's about it, I believe.

> The difference is conceptual, not in the representation. I don't
> agree that having a separate boolean type would be inconsistent.

A C++ bool is just as coercible as a char, of course.  The
added value, just like for char, is in overloading and,
exactly, representation (an array of char, or a vector of
bool, can be specialized to consume much less space than
arrays/vectors of int or long would) -- issues just not
pertinent to Python (you can 'import array', but what types
can be packed in what fashion into an array.array is quite
a different matter from what types exist as Python typeobjects).

Java takes a different approach to boolean coercion (not
consistent with the approach to _char_ coercion, which it
roughly shares with C or C++) but basically what it gets
from it is on the same plane -- strictly connected to
compile-time checks and operations of a statically typed
language.  You can overload a method differently for
boolean vs int arguments, you can get compiler errors
for some uses of int which the Java designers wanted to
forbid -- that's about it.

Without static typing, Python would of course get none of
these benefits... while still paying all of the costs (in
a conceptual sphere first of all) that it blissfully AVOIDS
by eschewing unnecessary distinctions (just as it avoids
distinguishing between characters and single-character
strings).


> Scheme is dynamically typed and does have separate true and false
> values. Lisp does not, but equates Booleans with the empty list and
> symbol t rather than 0 and 1. Smalltalk is dynamically typed and has
> separate Booleans.

Smalltalk's Booleans are used for runtime polymorphism --
you send an object an 'if: block' message and it responds
appropriately (executing, or not executing, the block).
In an *everything*-is-an-object mindset, that's great --
one less 'statement', one more *message* whose responding
method you can tweak &c.  Python has a much more traditional
approach to statements, and would draw no benefit from
type(i<j) != type(2+2), as it's not going to start sending
'messages' in lieu of good old if and while statements.

As for Scheme, the Revised(4) report says:

"""
Any Scheme value can be used as a boolean value for the
purpose of a conditional test. As explained in section
section Booleans, all values count as true in such a test
except for #f. This report uses the word "true" to refer
to any Scheme value that counts as true, and the word
"false" to refer to #f.

Note: In some implementations the empty list also counts
as false instead of true.
"""

Revised(5) report introduces a Boolean 'type', but it
still basically follows the same rules except for
removing the mention about empty-list counting as false
'in some implementations'.


If any value can be used as boolean, what's the big
gain in also having an 'alleged' Boolean type which
just duplicates what can be done with any other
object?

Note that Scheme also distinguished (in R5) 'char?'
from 'string?'; as it uses this level of fine
grainedness, I guess it IS consistent in having
these impractical 'boolean?' as well.

Python does NOT draw distinctions unless there is
practical use -- no char/string dichotomy; therefore,
for consistency, no boolean/all-other-which-can-be-
USED-as-boolean-but-'ARE'-not-boolean one either.

Korzybski and Wittgenstein might, I believe, appreciate
Python's pragmatic stance on this -- as it happens,
these two giants in the 20th century's reflections
on language, mind, and reality, were both engineers
(and, in spirit if not in degrees, I like to think
of our BDFL as a fellow engineer too... though I
guess that, actually being a mathematician and a
computer scientist by degree, he may be offended!-).


> I think it is only C and languages drawing conventions from C that
> equate booleans with numbers, with "any non-zero" meaning "true"
> and the canonical "true" value of 1.

I'm not sure what you mean here, but, either way, this
just doesn't ring true.  For example, Java surely draws
a lot from C, yet doesn't apply implicit cohercion to
numbers in a Boolean context or vv; BCPL, which we can
be *SURE* didn't "draw any convention from C" (since it
predated it!), and Forth (been a long time since I last
used it, but...), use numbers as booleans.

But, sure, the ability to *avoid* drawing certain semantic
distinctions at inappropriately-low levels (e.g., language
level, OS-level, etc) -- character versus string of length
1, boolean versus integer, textfile versus datafile, etc --
is anything but universal... that's why some languages,
OS's, etc, are better than others.  It's far too easy, in
this as in many other conceptual tasks, to be entrapped by
what Korzybski denounced as 'the IS of identity', to fail
to grasp the right 'family resemblance' as Wittgenstein
might put it; to think, in other words, that since we
cannot truly say 'a IS b' in the IS-of-identity sense,
then our language/OS/etc MUST distinguish a and b into
different classifications.

The right conceptual simplifications may only be invented
a few times, with others copying them from the inventors
(perhaps Postscript from Forth, C from BCPL, etc).

But the right test to apply is an operational semantic
one... what *concrete advantages* would accrue to Python
programmers if type(2>1) != type(2+1), with the rest of
the language staying basically the same?  (If you're
arguing for a _completely_ different language, e.g. one
based on modeling success/failure as non-data a la
Snobol or Icon, or a statically-typed one, with such
things as overloads &c, then it's better to clarify that;
me, I'm discussing issues related to, at most, incremental
changes in Python, not a complete rework to turn it into
a C++, Icon, Dylan, Scheme, or Smalltalk clone:-).


Alex






More information about the Python-list mailing list