checking if a list is empty

T

Terry Reedy

Th money-quote as regards using arbitrary objects in truth tests:

All this changed with the introduction of the two-element
boolean domain {true, false} which provides the vocabulary
needed to assign values to boolean expressions: 3<4 is a
way for writing true, 3>4 is a way for writing false,
whereas the value of x>0 depends on the value of x ...
[end quote]


In Python, [1, 2, 3] is another way of writing true, and [] is another
way of writing false. Similarly with any other arbitrary objects.

Another way to look at it is that Python automatically calls bool() on
every expression in its two boolean or conditional contexts: 'if e:' and
'while e'. This is a boilerplate-removing, labor-saving convenience.
Python has many such conveniences.
 
T

Terry Reedy

(True = True) is False

is a syntax error ;-)

and 'True = True' is a (useless) statement,
and statements do not have boolean values,
and 'True == True' *is* True, which is to say,
((True == True) is False) is False.
 
T

Terry Reedy

But it seems you did not get the moral? Spelt out: "Beware of lossy
compression!"
[Which is also the moral of my 'proof']

I get it now. As I suggested in response to Stephen, [] and [1] spell
False and True only in boolean contexts (if/while headers) where they
are implicitly wrapped with a bool() call, which is to say, where their
boolean value is extracted from them. As you point out, there is
information loss as all other context-irrelevant details are ignored.
 
R

rusi

rusi said:
[Steven quote]
In Python, [1, 2, 3] is another way of writing true, and [] is another
way of writing false. Similarly with any other arbitrary objects. The
only things that bools True and False are good for are:
<snipped>
[end Steven quote]
------------------------
So since
[1,2,3] is one way of writing True (lets call it True3)

No. Steven knew exactly why he was using “true” versus “True”. He's
explained why elsewhere in this thread. The former does not refer to the
Python boolean singleton, the latter does.

The only object that is True is the True singleton. But there are many
objects that are true.

Yes.
The python entities: {True, False} are not an exact (isomorphic) model
for the semantic boolean domain {true, false} (which is needed for
example to explicate the semantics of if while etc) Which is to say
the boolean type in python is not first class.
 
S

Steven D'Aprano

Mathematics has existed for millenia. Hindu-arabic numerals (base-10
numbers) have been known for about one millennium The boolean domain
is only a 100 years old. Unsurprisingly it is not quite 'first-class'
yet: See
http://www.cs.utexas.edu/users/EWD/transcriptions/EWD10xx/EWD1070.html
[Lifted fromhttp://c2.com/cgi/wiki?EqualVsTrueFalse]

Th money-quote as regards using arbitrary objects in truth tests:

   
    All this changed with the introduction of the two-element boolean
    domain {true, false} which provides the vocabulary needed to
    assign values to boolean expressions: 3<4 is a way for writing
    true, 3>4 is a way for writing false, whereas the value of x>0
    depends on the value of x ... [end quote]

In Python, [1, 2, 3] is another way of writing true, and [] is another
way of writing false. Similarly with any other arbitrary objects.

Well so is [1,2] another way of writing True

And then we get the interesting result that (True = True) is False

I presume you mean to say:

([1, 2] == True) is False

that is, that one true value is not equal to another true value.

That is correct. However, Python's == operator is not a Boolean Algebra
operator. If it were, it would probably be called "material
biconditional", or XNOR, and written ↔ or <-> and would be smart enough
to recognise that both [1, 2] and True are true.

Or possibly dumb enough... the difficulty is that the equality operator
knows more about the objects than just their truth value.

And furthermore:

([1, 2] and True) == (True and [1, 2])

is also False, again because == is too smart to recognise that the left
hand side (True) and the right hand side ([1, 2]) are both true values.

It's not that Python bools aren't first class objects, but that Python
doesn't have a full set of all 16 possible boolean algebra operators.
 
S

Steven D'Aprano

The python entities: {True, False} are not an exact (isomorphic) model
for the semantic boolean domain {true, false} (which is needed for
example to explicate the semantics of if while etc) Which is to say the
boolean type in python is not first class.

I'm afraid I don't understand what you mean. Can you explain please, what
properties of "first class booleans" do you think are missing from Python?
 
R

rusi

I'm afraid I don't understand what you mean. Can you explain please, what
properties of "first class booleans" do you think are missing from Python?


Dijkstra's writings I alluded to, take a logic/math line to this. Let
me try to rephrase Dijkstra (who is now sadly not able to defend our
(mis)understandings of his writings) in a more linguistic way:

In English when we say something like "x is y" the y (predicate) can
be an adjective phrase -- the apple is red -- or a noun phrase -- the
apple is a fruit.

They seem similar; they are very different -- you agree??

From times immemorial 'true' and 'false' have been used in the
adjective sense: eg Such-and-such statement is true.
Boole's contribution -- actually Dijkstra's recognition of Boole's
contribution -- is that dignifying {true, false} from adjectives to
nouns -- the boolean domain -- fundamentally alter and improve the
rules and possibilities for our thinking. [See his puzzles in the same
paper:
http://www.google.com/url?sa=D&q=ht...users/EWD/transcriptions/EWD10xx/EWD1070.html

As an analogy for this consider arithmetic.

Even primitive people can count: My 3 children, my 5 sheep. They do
this with the ordinals -- first child, second child, third child...
But arithmetic cannot really take off until we allow these numbers
(ordinals) to be dignified into entities in their own right --
cardinals.
ie the mathematician needs to believe in the existence of the numbers
1,2 etc for him to do his job well.

[As an aside I may mention that philosophers of mathematicians will
call this platonism: "In which heaven do these numbers exist?"
And platonism is mysticism. And mysticism is bullshit. But the vast
majority of practicing mathematicians refuse to be dislodged from
their 'platonic heaven.' For them mathematics can only be done if it
is done in 'discovery' mode and not in 'invention' mode.]

And so just as good math happens by believing that the numbers exist
and discovering their properties, good logic happens when we believe
that {True, False} exist (in some platonic heaven). Which is to say
they should be nouns in our language.

Well that in summary is the Boole's ideology (Dijkstra's evangelism)
understood linguistically and independent of python/programming.

Reapplied back to the math/programming field, we find that if a value-
domain (data-type) has to be first-class, it at the least has to be a
denotable entity in the language which should be conformable with its
abstract/expected properties.
For example if my language seems to have entities like '2' '3' '+' but
2+3 does not work out equal to 5 we would (I hope!) not say the
language has first-class numbers.

But in order for any of this discussion to be possible, equality
should be well-defined.
Which means that in addition to being an equivalence relation it must
have substitutivity
http://en.wikipedia.org/wiki/Equality_(mathematics)#Some_basic_logical_properties_of_equality
which is another form of a very fundamental principle attributed to
Leibniz, the principle of identity of indiscernibles:
http://en.wikipedia.org/wiki/Leibniz's_law

Seemingly you and Dijkstra are saying something similar when you say
[1,2,3] is a way of writing true
and he says 2<3 is a way of writing true.
But on further examination (with Leibniz law above) Dijkstra's 2<3 =
True will work consistently in all contexts but [1,2,3] = True will
work sometimes and fail sometimes.

In mathSpeak we say, the definition of bool is not well defined
In CSSpeak we say the definition is not first class.

In the language of algebraic specifications, the slogan is "No
confusion, No junk"
eg http://www.informatik.uni-bremen.de/agbkb/lehre/ws06-07/casl/slides/Datatypes-II.pdf

This is usually applied to specific models in a given language

But it could as well be applied to the models that a language supplies
by default.
And when we apply it to python's bool as a model of the abstract/math
concept bool it has confusion and junk.
 
T

Terry Reedy

Given the usual CS definition of 'first class object', all Python
objects are first class. But that does not preclude other definitions.
Dijkstra's writings I alluded to, take a logic/math line to this. Let
me try to rephrase Dijkstra (who is now sadly not able to defend our
(mis)understandings of his writings) in a more linguistic way:

In English when we say something like "x is y" the y (predicate) can
be an adjective phrase -- the apple is red -- or a noun phrase -- the
apple is a fruit.

They seem similar; they are very different -- you agree??

Sometimes. Sometimes it could mean 'the apple is fruity' or 'the apple
has the characters that define the wider grouping of fruits'. "John is
brilliant", "John is a brilliant man", and "John is a genius" (there is
no 'a brilliant') pretty much have the same effective meaning. But I get
the point about reification.
From times immemorial 'true' and 'false' have been used in the
adjective sense: eg Such-and-such statement is true.
Boole's contribution -- actually Dijkstra's recognition of Boole's
contribution -- is that dignifying {true, false} from adjectives to
nouns -- the boolean domain -- fundamentally alter and improve the
rules and possibilities for our thinking. [See his puzzles in the same
paper:
http://www.google.com/url?sa=D&q=ht...users/EWD/transcriptions/EWD10xx/EWD1070.html

As an analogy for this consider arithmetic.

Even primitive people can count: My 3 children, my 5 sheep. They do
this with the ordinals -- first child, second child, third child...
But arithmetic cannot really take off until we allow these numbers
(ordinals) to be dignified into entities in their own right --
cardinals.
ie the mathematician needs to believe in the existence of the numbers
1,2 etc for him to do his job well.

[As an aside I may mention that philosophers of mathematicians will
call this platonism: "In which heaven do these numbers exist?"
And platonism is mysticism. And mysticism is bullshit. But the vast
majority of practicing mathematicians refuse to be dislodged from
their 'platonic heaven.' For them mathematics can only be done if it
is done in 'discovery' mode and not in 'invention' mode.]

And so just as good math happens by believing that the numbers exist
and discovering their properties, good logic happens when we believe
that {True, False} exist (in some platonic heaven). Which is to say
they should be nouns in our language.

Well that in summary is the Boole's ideology (Dijkstra's evangelism)
understood linguistically and independent of python/programming.

Reapplied back to the math/programming field, we find that if a value-
domain (data-type) has to be first-class, it at the least has to be a
denotable entity in the language which should be conformable with its
abstract/expected properties.
For example if my language seems to have entities like '2' '3' '+' but
2+3 does not work out equal to 5 we would (I hope!) not say the
language has first-class numbers.

You seem to equate 'number' with 'natural number' in the classical
sense. If '2' and '3' are residue classes (remainers) mod 5, then 2 + 3
is 0. Even kids understand clock arithmetics. Of course,
the 24 hour (0 to 23 hourse) is saner than the older 1-12,am/pm system,
but kids even manage with that.
But in order for any of this discussion to be possible, equality
should be well-defined.
Which means that in addition to being an equivalence relation it must
have substitutivity
http://en.wikipedia.org/wiki/Equality_(mathematics)#Some_basic_logical_properties_of_equality
which is another form of a very fundamental principle attributed to
Leibniz, the principle of identity of indiscernibles:
http://en.wikipedia.org/wiki/Leibniz's_law

Seemingly you and Dijkstra are saying something similar when you say
[1,2,3] is a way of writing true
and he says 2<3 is a way of writing true.
But on further examination (with Leibniz law above) Dijkstra's 2<3 =
True will work consistently in all contexts

In general, a < b will work consistently as generally expected of total
orders if, but only if, a and b are members of a totally ordered set and
< indicates that total order. If '<' represents a partial order, 'a<b'
may be undefined or defined as false when 'b<a' is also false.
but [1,2,3] = True will work sometimes and fail sometimes.

'Bool(<normal expression*>) is a much a spelling of true or false as 'a
< b'. It works just as consistently in all contexts.

*nornal expression: evaluates to an object with a well-defined boolean
value, which is to say, causes bool() to return True or False.
In mathSpeak we say, the definition of bool is not well defined

The math definition of bool or the Python definition?
And what definition of 'well-defined'? On builtins, bool(ob) always
returns the same value. And the values are pretty consistent.
In CSSpeak we say the definition is not first class.

What CS definition?
 
S

Steven D'Aprano

[snip]

I'm afraid I didn't find your discussion about reification, Platonism and
linguistics very helpful. Some of it I disagree with, some I agree with,
but in neither case do I see any relevance to the question of whether
bools are first class objects in Python, and if not, why not.

Reapplied back to the math/programming field, we find that if a value-
domain (data-type) has to be first-class, it at the least has to be a
denotable entity in the language which should be conformable with its
abstract/expected properties.

Now you're getting somewhere!
For example if my language seems to have entities like '2' '3' '+' but
2+3 does not work out equal to 5 we would (I hope!) not say the language
has first-class numbers.

Well, that's a problem. By that definition, floats are not first class
numbers. While 2+3 does work out to be equal to 5, other standard
properties of the real number system do not apply:
False

Similarly, in many languages (including older versions of Python),
neither are integers:
Traceback (innermost last):
File "<stdin>", line 1, in ?
OverflowError: integer addition


Other languages may wrap around, giving -1 or -2147483648.

So it seems that either we're forced to accept that neither floats nor
integers are "first class", or instead back-track and ask:

"Hang on, who decides what the expected properties are?"


But in order for any of this discussion to be possible, equality should
be well-defined.
Which means that in addition to being an equivalence relation it must
have substitutivity


Can you show us a problem that is hard to solve in Python because ([1,2]
and True) evaluates as True, but ([1,2] == True) evaluates as False?


http://en.wikipedia.org/wiki/Equality_(mathematics% 29#Some_basic_logical_properties_of_equality
which is another form of a very fundamental principle attributed to
Leibniz, the principle of identity of indiscernibles:
http://en.wikipedia.org/wiki/Leibniz's_law

But Python truth values are not indiscernible. Do you think they must be?

If they are indiscernible, there can only be two unique values (possibly
spelled "Veritas" and "Falsus" to avoid confusion with Python's True and
False). But why must they be indiscernible?

Seemingly you and Dijkstra are saying something similar when you say
[1,2,3] is a way of writing true
and he says 2<3 is a way of writing true. But on further examination
(with Leibniz law above) Dijkstra's 2<3 = True will work consistently in
all contexts but [1,2,3] = True will work sometimes and fail sometimes.

Please do not arbitrarily mix Python and mathematics syntax. What you
have stated gives a SyntaxError.

[1,2,3] == True will work always, or you have a very buggy version of
Python. It will always return False, as expected.


I suspect that in a boolean context, the operator you want is material
biconditional, or XNOR, also known as "p if and only if q". Python does
not have this as a built-in, but it's easy enough to write it:

def xnor(p, q):
if p: return q
else: return p if q else True

(I have deliberately written it to return one of the two arguments when
possible. If you don't care for this behaviour, the else clause is even
simpler: return not q)

If you don't like the name XNOR, rename it "equals" and be done. Nobody
says that equality *must* be spelled with = or == as an infix operator.
That would be a foolish insistence.

Another way would be to compare the canonical truth values for equality:

bool(p) == bool(q)

but of course there's nothing special about the canonical truth values
except ease of use. One could choose any other values:

def canonical(flag):
if flag: return "Nobody expects the Spanish Inquisition!!!"
else: return None

canonical(p) == canonical(q)

The important thing is that Python's sense of equality doesn't just apply
in the boolean domain, it applies to the broader any-arbitrary-Python-
object domain. Python's equals is too powerful to be limited to Python's
truth values: it needs to distinguish between 42 and 23, while in the
boolean domain one need not.

Consequently, if you want equality in the boolean domain, you need to use
something other than the built-in == operator. Python doesn't allow you
to override == for built-in objects, so the simplest, most straight-
forward way is with a function. Using such a function:
equals = xnor
equals( equals([1, 2], 42), equals("spam", 23) )
23

which is, naturally, just another way of spelling True.


In mathSpeak we say, the definition of bool is not well defined In
CSSpeak we say the definition is not first class.

That is not the normal definition of "first class" in computer science.
The normal definition relates to whether a data type can be assigned to
variables, passed to functions, and otherwise treated like ints or floats
or other "first class" types. That certainly applies to truth values in
Python, and bools.

In the language of algebraic specifications, the slogan is "No
confusion, No junk"
eg
http://www.informatik.uni-bremen.de/agbkb/lehre/ws06-07/casl/slides/ Datatypes-II.pdf

This is usually applied to specific models in a given language

But it could as well be applied to the models that a language supplies
by default.
And when we apply it to python's bool as a model of the abstract/math
concept bool it has confusion and junk.

Well there is certainly confusion, but it's not in Python's model. The
confusion seems to entirely rest in your mistake in thinking that the
only valid way to do an equality test is with the built-in == syntax.
 
H

harrismh777

rusi said:
But on further examination (with Leibniz law above) Dijkstra's 2<3 =
True will work consistently in all contexts but [1,2,3] = True will
work sometimes and fail sometimes.

It would have to be written 2<3 == True; [1,2,3] == True; otherwise,

....

+1 QOTW
 
T

Terry Reedy

On 5/15/2011 1:33 PM, rusi wrote:

at
http://www.cs.utexas.edu/users/EWD/transcriptions/EWD10xx/EWD1070.html

"Acquiring that familiarity requires what in these financial times is
known as "intellectual investment"; you can take my word for it that
this investment quickly pays off."

I recommend understanding the following as three more "intellectual
investments":

We create a Boolean domain by drawing a distinction in some domain and
treating everything on each side of the distinction as equal in some
value. A Boolean value or variable represents such a dichotomy, a choice
between two all-inclusive but mutually exclusive possibilities. Boole
derived his domain from truth/falsity of propositions. But that is an
interpretation of his abstract model and only one of endless possibilities.

This realization that switching networks are another interpretation is
the basis of digital computation. Boolean algebra theorems are theorems
about switching networks and can be used to design such networks. Such
networks can be used to do boolean arithmetic. The trick is to coerce
physical components into one of two states. Part of the trick is to not
look when they are transiting between them.

For its built-in information objects, Python choose 'representation of
something' versus 'representation of nothing' as the dichotomy. It
matches 'something' to True and 'nothing' to False as this is generally
more useful than the opposite matching. In boolean contexts, it
automatically fetches the boolean value of an object.
 
R

rusi

I have been scolded off-list for pursuing a discussion that has
nothing to do with python.
So I continue a bit gingerly :) and will stop when others feel this
is useless/irrelevant/whatever.
I'm afraid I didn't find your discussion about reification, Platonism and
linguistics very helpful. Some of it I disagree with, some I agree with,
but in neither case do I see any relevance to the question of whether
bools are first class objects in Python, and if not, why not.

Thank you (Steven and Terry) for using the word 'reification'. I used
the more common 'firstclass' because I assumed that will be more
generally known. I however prefer reification since one can discuss
(more cooly :) ) what and how much one should reify; the word
reification has less of a strong value judgment in philosophy than
firstclass has in computer science.

The lead-writeup on reification http://en.wikipedia.org/wiki/Reification_(computer_science)
has the following line:
Informally, reification is often referred to as "making something a first-class citizen" within the scope of a particular system.

So from the CS side reification == movement-towards-firstclassness
From the philosophical side we could try to define platonism (non-
mystically) as "The strong reification of abstract concepts"

So much for my defense of bringing in platonism into the discussion.
Seemingly you and Dijkstra are saying something similar when you say
[1,2,3] is a way of writing true
and he says 2<3 is a way of writing true. But on further examination
(with Leibniz law above) Dijkstra's 2<3 = True will work consistently in
all contexts but [1,2,3] = True will work sometimes and fail sometimes.
Please do not arbitrarily mix Python and mathematics syntax. What you have stated gives a SyntaxError.

Is this non-mixing-up possible? Like 'reification,' I do not know if
using the funny brackets of denotational semantics would be
intelligible on this list ( and I dont know how to write them in
ASCII) but using |[ ]| as an approximation, I would have to say
something like:

Dijkstra's |[ 2<3 ]| = True will work consistently... Python's |
[ [1,2,3] ]| = |[True ]| will be be true in boolean contexts and not
elsewhere.
Note that the first |[]| is for the object language called mathematics
and the other two for the object language called python. And the = is
in a pidgin English-math meta language that is need to discuss these
object languages.

I am not clear that this form of discourse actually enhances clarity,
however it does bring up the point that this discussion is as much
about object/meta-language distinctions and confusions as it is about
reification.

You see when Terry talks of boolean algebra for switching networks, he
is referring to logic as an object language.
But when we use logic to discuss and understand (and argue :) ) we
are using it in the meta-language.

Dijkstra's signal contribution -- which he attributes to Boole,
Leibniz and Recorde (for the = sign) -- lies in this:
From the time of Aristotle, all usage of logic in the meta-language
(logic as the substrate for arguments rather than logic as a model for
things like switching networks) has been a string of assertions
linked up with 'implies' 'therefore' 'follows from' etc. All these
when modelled (in a suitable object logic) would traditionally look
like => (implies) or at best <= (follows from)

It is possible to do all this -- traditional logic -- using = (aka
iff, <=>, etc)

The benefit is that logic becomes much more like traditional algebra:
Proofs become of the form:

desideradum
=
:
:
= true

The cost is that bool has to be properly reified.
Well, that's a problem. By that definition, floats are not first class
numbers. While 2+3 does work out to be equal to 5, other standard
properties of the real number system do not apply:

From C onwards (and in Fortran), its been called float, not real.
Note that C like python uses a math-suggesting name int for integers
but a hardware implementation name for float. This suggests that
(aside from overflow) int in C corresponds to the math Z whereas float
does not quite correspond to real. [The whole field of numerical
analysis comes about because of this non-correspondence]

In the language Pascal, what we call float today was called real and
this would be an argument.
But in this context I dont get the argument...
 
R

rusi

Given the usual CS definition of 'first class object', all Python
objects are first class. But that does not preclude other definitions.

<snipped>

What CS definition?

Perhaps your definition matches the wikipedia article:
http://en.wikipedia.org/wiki/First-class_object

And I am using the extended definition on the talk page:
http://en.wikipedia.org/wiki/Talk:First-class_object#Is_it_is.2C_or_is_it_aint.3F

[Evidently the arguments of this thread are repeatedly played out
elsewhere :-; ]
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,770
Messages
2,569,584
Members
45,075
Latest member
MakersCBDBloodSupport

Latest Threads

Top