Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

PEP308: Yet another syntax proposal

1 view
Skip to first unread message

Raymond Hettinger

unread,
Feb 10, 2003, 10:52:24 AM2/10/03
to
I suggest:

cond ?? val1 || val2

* Having two characters at each step helps visually segregate the
components.
* The ?? and || strongly suggest testing and alternation.
* Doesn't overload or confuse with existing operators.
* No new keywords.
* In-order presentation.
* Short and easy to read.


Using Martin Maney's live code examples, here's what it looks like:
i = j>=0 ?? j || n
sy = d0.year - (d0.month<7 ?? 1 || 0)
add2url = '?' + (params.has_key('add2url') ?? params['add2url'] ||
'')
tail = (len(events)>1 ?? ' ' || '<br>') + tail


Raymond Hettinger


Anton Muhin

unread,
Feb 10, 2003, 11:04:33 AM2/10/03
to
It seems almost ideal for me :)

Anton.

Aahz

unread,
Feb 10, 2003, 11:44:18 AM2/10/03
to
In article <YUP1a.3080$SB2...@nwrddc03.gnilink.net>,

Raymond Hettinger <pyt...@rcn.com> wrote:
>
>I suggest:
>
> cond ?? val1 || val2

+0.5

I still have yet to see a clear explanation of why short-circuit is
necessary and therefore iif() unreasonable.
--
Aahz (aa...@pythoncraft.com) <*> http://www.pythoncraft.com/

Register for PyCon now! http://www.python.org/pycon/reg.html

Sheila King

unread,
Feb 10, 2003, 12:16:54 PM2/10/03
to
On Mon, 10 Feb 2003 15:52:24 GMT, "Raymond Hettinger"
<vze4...@verizon.net> wrote in comp.lang.python in article
<YUP1a.3080$SB2...@nwrddc03.gnilink.net>:

> I suggest:
>
> cond ?? val1 || val2
>
> * Having two characters at each step helps visually segregate the
> components.
> * The ?? and || strongly suggest testing and alternation.

To whom? The || would only suggest alternation to those who have already
programmed in languages where this is the symbol for "or".

> * Doesn't overload or confuse with existing operators.
> * No new keywords.
> * In-order presentation.
> * Short and easy to read.
>
>
> Using Martin Maney's live code examples, here's what it looks like:
> i = j>=0 ?? j || n
> sy = d0.year - (d0.month<7 ?? 1 || 0)
> add2url = '?' + (params.has_key('add2url') ?? params['add2url'] ||
> '')
> tail = (len(events)>1 ?? ' ' || '<br>') + tail

Ick.

I would have to agree with what David Eppstein says in
Message-ID: <eppstein-101ADB...@news.service.uci.edu>

"Why do people keep proposing cryptic punctuation-based syntax for this?
Using punctuation instead of words makes the meaning non-obvious,
especially to new programmers who have not used C/C++/Java, and so it
seems unlikely that the BDFL will ever accept it. Such proposals
clutter the discussion without making progress towards getting a ternary
included in the language."

--
Sheila King
http://www.thinkspot.net/sheila/
http://www.k12groups.org/

Raymond Hettinger

unread,
Feb 10, 2003, 12:35:01 PM2/10/03
to
"Aahz" <aa...@pythoncraft.com>

> I still have yet to see a clear explanation of why short-circuit is
> necessary and therefore iif() unreasonable.

It is necessary when:
1. One of the alternatives has a side-effect; or
2. one or both alternatives are time consuming; or
3. the validity of the alternatives depends on the outcome
of the test.

# Example where all three reasons apply
data = isinstance(source, str) ?? source.readlines() || source.split()

1. readlines() moves the file pointer
2. for long sources, both alternatives take time
3. split() is only valid for strings and readlines() is only
valid for file objects.


Raymond Hettinger


Raymond Hettinger

unread,
Feb 10, 2003, 12:48:40 PM2/10/03
to
> "Aahz" <aa...@pythoncraft.com>
> > I still have yet to see a clear explanation of why short-circuit is
> > necessary and therefore iif() unreasonable.
>
> It is necessary when:
> 1. One of the alternatives has a side-effect; or
> 2. one or both alternatives are time consuming; or
> 3. the validity of the alternatives depends on the outcome
> of the test.
>
> # Example where all three reasons apply
> data = isinstance(source, str) ?? source.readlines() ||
source.split()

That should have been:
isinstance(source, file)


Raymond Hettinger


Aahz

unread,
Feb 10, 2003, 12:49:29 PM2/10/03
to
In article <9pR1a.22187$F25....@nwrddc02.gnilink.net>,

You're missing the point. How frequently does this occur such that
getting all our knickers in a twist is worth it? So far, most of the
examples pushing a conditional expression have *NOT* required
short-circut behavior. For the cases where side-effects restrict the
use of a conditional expression, I think perhaps requiring the use of an
if statement is the most appropriate way to handle it.

David Eppstein

unread,
Feb 10, 2003, 12:59:01 PM2/10/03
to
In article <b28on9$a3l$1...@panix2.panix.com>, aa...@pythoncraft.com (Aahz)
wrote:

> You're missing the point. How frequently does this occur such that
> getting all our knickers in a twist is worth it? So far, most of the
> examples pushing a conditional expression have *NOT* required
> short-circut behavior. For the cases where side-effects restrict the
> use of a conditional expression, I think perhaps requiring the use of an
> if statement is the most appropriate way to handle it.

My feeling is that the reason for short circuiting isn't so much because
of side effects (I think we should try to keep expressions as free of
side effects as possible) but because one or both of the two sides may
be undefined and raise an exception if the guard condition is not met.

--
David Eppstein UC Irvine Dept. of Information & Computer Science
epps...@ics.uci.edu http://www.ics.uci.edu/~eppstein/

Raymond Hettinger

unread,
Feb 10, 2003, 1:00:53 PM2/10/03
to

"Sheila King" <use...@thinkspot.net> wrote in message
news:b27qm...@kserver.org...

> > * The ?? and || strongly suggest testing and alternation.
>
> To whom? The || would only suggest alternation to those who have already
> programmed in languages where this is the symbol for "or".

In python, | is the symbol for bitwise-or.
When paired with ?? with || the meaning is further clarified.


> "Why do people keep proposing cryptic punctuation-based syntax for this?

Because:
1. New keyword proposals are doomed
2. Bending old keywords creates ambiguity
3. Punctuation operators work well in expressions.
Who (except a COBOL programmer) would want:
2 plus 3 times 5
4. Reading through the provided live code examples,
it is much clearer than keyword alternatives
5. I spent an afternoon finding the least cryptic
form of punctuation I could think of.
The only close alternative was:
x = cond ?? val1 :: val2
I felt || was better because colons were
already so heavily loaded.


Raymond Hettinger


Dave Brueck

unread,
Feb 10, 2003, 1:23:11 PM2/10/03
to
On Mon, 10 Feb 2003, Aahz wrote:

> In article <YUP1a.3080$SB2...@nwrddc03.gnilink.net>,
> Raymond Hettinger <pyt...@rcn.com> wrote:
> >
> >I suggest:
> >
> > cond ?? val1 || val2
>
> +0.5
>
> I still have yet to see a clear explanation of why short-circuit is
> necessary

Short-circuit evaluation is never "necessary" in _any_ language - it's
just very, very useful sometimes. Python's 'and' operator doesn't _have_
to be a short-circuit operator, but it's far more useful because it is.

> and therefore iif() unreasonable.

Several of the previous examples have already illustrated this:

z = iif(x, x.getPref(), 'Not specified')

is broken without short-circuiting.

-Dave

Harvey Thomas

unread,
Feb 10, 2003, 11:59:48 AM2/10/03
to
Aahz wrote:

> In article <YUP1a.3080$SB2...@nwrddc03.gnilink.net>,
> Raymond Hettinger <pyt...@rcn.com> wrote:
> >
> >I suggest:
> >
> > cond ?? val1 || val2
>
> +0.5
>
> I still have yet to see a clear explanation of why short-circuit is

> necessary and therefore iif() unreasonable.
> --
> Aahz (aa...@pythoncraft.com) <*>

Unless I'm missing the point completely, compare:

if cond:
x = calc(1, resource_intensive_1())
else:
x = calc(1, resource_intensive_2())

with

x = calc(1, iif(cond, resource_intensive_1(), resource_intensive_2()))

In the second case both resource_intensive_1() and resource_intensive_2()
are evaluated. There is of course the possibility of undesired side-effects.

You can warn people to not use iif for such cases, but you won't stop it being used wrongly.


_____________________________________________________________________
This message has been checked for all known viruses by the MessageLabs Virus Scanning Service.

sism...@hebmex.com

unread,
Feb 10, 2003, 11:46:54 AM2/10/03
to
> From: aa...@pythoncraft.com [mailto:aa...@pythoncraft.com]
> Sent: Monday, February 10, 2003 10:44 AM

>
> In article <YUP1a.3080$SB2...@nwrddc03.gnilink.net>,
> Raymond Hettinger <pyt...@rcn.com> wrote:
> >
> >I suggest:
> >
> > cond ?? val1 || val2
>
> +0.5
>
> I still have yet to see a clear explanation of why short-circuit is
> necessary and therefore iif() unreasonable.
> --
> Aahz (aa...@pythoncraft.com) <*>
> http://www.pythoncraft.com/

Given that objects may now have property attributes,
where just checking the value of an attribute may ("may")
dispatch several actions to return said value, short-
circuiting expression evaluations is the correct way
to implement this.

-gustavo

holger krekel

unread,
Feb 10, 2003, 12:32:08 PM2/10/03
to
Harvey Thomas wrote:
> Unless I'm missing the point completely, compare:
>
> if cond:
> x = calc(1, resource_intensive_1())
> else:
> x = calc(1, resource_intensive_2())
>
> with
>
> x = calc(1, iif(cond, resource_intensive_1(), resource_intensive_2()))
>
> In the second case both resource_intensive_1() and resource_intensive_2()
> are evaluated. There is of course the possibility of undesired side-effects.

I don't mind having to write the 4-liner if i execute
"resource_intensive" functions. I would say that *especially* when
you have "huge" functions with side effects you should choose the 4-liner
over an expression. Often the two functions will have different
arguments where you need to adapt to. Adding this logic to the
already-too-long expressions becomes a pain to maintain and read.

far more often a ternary op is used to switch between two strings
or two numbers aka

result = input=='y' and "yes" or "no"

and has the net side effect that people (must) understand in their
learning process how and & or works in Python. Calling different
methods hints at conditional control-flow and that is better done
with an easy-to read if-statement which supports you by
indentation i.e. visual clues.

holger

Aahz

unread,
Feb 10, 2003, 1:25:46 PM2/10/03
to
In article <eppstein-A7834B...@news.service.uci.edu>,

David Eppstein <epps...@ics.uci.edu> wrote:
>In article <b28on9$a3l$1...@panix2.panix.com>, aa...@pythoncraft.com (Aahz)
>wrote:
>>
>> You're missing the point. How frequently does this occur such that
>> getting all our knickers in a twist is worth it? So far, most of the
>> examples pushing a conditional expression have *NOT* required
>> short-circut behavior. For the cases where side-effects restrict the
>> use of a conditional expression, I think perhaps requiring the use of an
>> if statement is the most appropriate way to handle it.
>
>My feeling is that the reason for short circuiting isn't so much because
>of side effects (I think we should try to keep expressions as free of
>side effects as possible) but because one or both of the two sides may
>be undefined and raise an exception if the guard condition is not met.

That's still not addressing my point: how often is short-circuit
evaluation needed? That's the *only* reason to consider conditional
expressions rather than a new builtin conditional function.

Aahz

unread,
Feb 10, 2003, 1:26:38 PM2/10/03
to
In article <mailman.104489704...@python.org>,

Dave Brueck <da...@pythonapocrypha.com> wrote:
>On Mon, 10 Feb 2003, Aahz wrote:
>> In article <YUP1a.3080$SB2...@nwrddc03.gnilink.net>,
>> Raymond Hettinger <pyt...@rcn.com> wrote:
>>>
>>>I suggest:
>>>
>>> cond ?? val1 || val2
>>
>> +0.5
>>
>> I still have yet to see a clear explanation of why short-circuit is
>> necessary
>
>Short-circuit evaluation is never "necessary" in _any_ language - it's
>just very, very useful sometimes. Python's 'and' operator doesn't _have_
>to be a short-circuit operator, but it's far more useful because it is.

"Far more useful", eh? You need to argue that, not just claim it.

Andrew Dalke

unread,
Feb 10, 2003, 1:43:08 PM2/10/03
to
Raymond Hettinger

> > # Example where all three reasons apply
> > data = isinstance(source, str) ?? source.readlines() ||
> source.split()
>
> That should have been:
> isinstance(source, file)

Err, that should have been

if hasattr(source, "readlines"):
lines = source.readlines()
else:
lines = source.split()

Or perhaps better as
try:
lines = source.readlines()
except AttributeError;
lines = source.split()

Or for cases where you strongly prefer a file but will accept
a raw string (which you shouldn't do since StringIO is so easy
to get)

if isinstance(source, basestring):
source = StringIO(source)
...

and then you can change the alorithm to use read, readlines,
etc. as need be.

Andrew
da...@dalkescientific.com

Andrew Dalke

unread,
Feb 10, 2003, 1:48:12 PM2/10/03
to
Aahz:

> You're missing the point. How frequently does this occur such that
> getting all our knickers in a twist is worth it? So far, most of the
> examples pushing a conditional expression have *NOT* required
> short-circut behavior. For the cases where side-effects restrict the
> use of a conditional expression, I think perhaps requiring the use of an
> if statement is the most appropriate way to handle it.

Extroplating from my earlier analysis, previously I noted that the
if/else expression will be used appropriately about 1 in every 1,000
lines of Python code. (Based upon inspection of existing C, C++,
and Python code.)

As I recall, nearly all cases (perhaps 9 of 10) did not involve
a case where short-circuiting was relevant -- both sides of the
expression could be evalutated without side effect. In addtition,
in a majority of those cases (perhaps 3 in 4) the branches were
constant, as in a simple number or string, so there is very little
performance gain.

That suggests that short circuiting if/else expression will be used
appropriately about once every 4,000 to 10,000 lines of Python
code.

Andrew
da...@dalkescientific.com


sism...@hebmex.com

unread,
Feb 10, 2003, 1:38:36 PM2/10/03
to
> From: aa...@pythoncraft.com [mailto:aa...@pythoncraft.com]
> Sent: Monday, February 10, 2003 12:26 PM

>
> >My feeling is that the reason for short circuiting isn't so
> >much because of side effects (I think we should try to keep
> >expressions as free of side effects as possible) but because
> >one or both of the two sides may be undefined and raise an
> >exception if the guard condition is not met.
>
> That's still not addressing my point: how often is short-circuit
> evaluation needed? That's the *only* reason to consider conditional
> expressions rather than a new builtin conditional function.

My question is "why leave it half-done?"

Why create a simple builtin function which doesn't do
short circuiting and then resort to half-baked hacks
when you do need it, when here's the chance to do it
fully and have a sanctioned short-circuiting ternary
operator, usable in all the cases the builtin would
work, and then some.

-gustavo

holger krekel

unread,
Feb 10, 2003, 1:36:36 PM2/10/03
to
David Eppstein wrote:
> In article <b28on9$a3l$1...@panix2.panix.com>, aa...@pythoncraft.com (Aahz)
> wrote:
>
> > You're missing the point. How frequently does this occur such that
> > getting all our knickers in a twist is worth it? So far, most of the
> > examples pushing a conditional expression have *NOT* required
> > short-circut behavior. For the cases where side-effects restrict the
> > use of a conditional expression, I think perhaps requiring the use of an
> > if statement is the most appropriate way to handle it.
>
> My feeling is that the reason for short circuiting isn't so much because
> of side effects (I think we should try to keep expressions as free of
> side effects as possible) but because one or both of the two sides may
> be undefined and raise an exception if the guard condition is not met.

right. in which case learning about and/or (which you have to anyway)
often helps. Because of the "y is false" problem in "x and y or z"
there are some cases where it doesn't fit. Do we have real code
examples for them?

holger

holger krekel

unread,
Feb 10, 2003, 1:41:54 PM2/10/03
to
Dave Brueck wrote:
> On Mon, 10 Feb 2003, Aahz wrote:
>
> > In article <YUP1a.3080$SB2...@nwrddc03.gnilink.net>,
> > Raymond Hettinger <pyt...@rcn.com> wrote:
> > >
> > >I suggest:
> > >
> > > cond ?? val1 || val2
> >
> > +0.5
> >
> > I still have yet to see a clear explanation of why short-circuit is
> > necessary
>
> Short-circuit evaluation is never "necessary" in _any_ language - it's
> just very, very useful sometimes. Python's 'and' operator doesn't _have_
> to be a short-circuit operator, but it's far more useful because it is.
>
> > and therefore iif() unreasonable.
>
> Several of the previous examples have already illustrated this:
>
> z = iif(x, x.getPref(), 'Not specified')
>
> is broken without short-circuiting.

yes, but it is easily written with an and-expression

z = not x and 'Not specified' or x.getPref()

and a ternary op would simply add another possibility.
A new ternary op can't be so good as to wipe out the
need (and all the existing code) for and/or behaviour.
In which case you have to learn two constructs.

Now if we had

z = x.getPref() except AttributeError: 'Not specified'

that might add something which we didn't have before
(in an expression).

holger

Andrew Koenig

unread,
Feb 10, 2003, 2:37:42 PM2/10/03
to
holger> right. in which case learning about and/or (which you have to
holger> anyway) often helps. Because of the "y is false" problem in
holger> "x and y or z" there are some cases where it doesn't fit. Do
holger> we have real code examples for them?

Yes -- as I've noted elsewhere in this discussion, Lib/unittest.py
actually contains a (minor) bug because it uses and/or where it
doesn't fit. The code is on lines 618-619:

self.stream.writeln("Ran %d test%s in %.3fs" %
(run, run == 1 and "" or "s", timeTaken))

--
Andrew Koenig, a...@research.att.com, http://www.research.att.com/info/ark

Alex Martelli

unread,
Feb 10, 2003, 2:54:53 PM2/10/03
to
Andrew Dalke wrote:
...

> Or perhaps better as
> try:
> lines = source.readlines()
> except AttributeError;
> lines = source.split()

This popular idiom has a slight imperfection. If source is an
object that has a buggy readlines method (and the bug makes
it raise AttributeError), as well as a working split method,
this idiom hides the bug and unintendedly falls through to
the call to the split method. The "right" way is something
just a tad more accurate/careful, such as:

try: method = source.readlines


except AttributeError: lines = source.split()

else: lines = method()

or variants thereof. The key issue: when you catch an
AttributeError as an expected indication of "this object
has no such method", make sure you ONLY _access_ the
method object in the try clause, then call it later,
generally in an else clause -- so you won't accidentally
catch AttributeError exceptions propagated by _calling_
a method that is actually there.

This relates to the above-quoted, slightly imperfect variant
of "easier to ask forgiveness than permission" (EAFP), a
bit like "Accurate LBYL" (Look Before You Leap) stands
to common or garden LBYL, whence my name for it...


Alex

Andrew Dalke

unread,
Feb 10, 2003, 3:52:36 PM2/10/03
to
Andrew Koenig:

> Yes -- as I've noted elsewhere in this discussion, Lib/unittest.py
> actually contains a (minor) bug because it uses and/or where it
> doesn't fit. The code is on lines 618-619:
>
> self.stream.writeln("Ran %d test%s in %.3fs" %
> (run, run == 1 and "" or "s", timeTaken))

And I've noted elsewhere (so no need to followup on this thread)
that from that snippet it appear that the person who wrote this
has more exprience in using other languages (hence the strange
use of 'writeln') than Python, so that this is perhaps not the best
indicator of an apropriate Python solution.

On the other hand, it suggests that an if/else expression would
make for fewer mistakes caused by people with experience in
if/else from other languages.

My other comments stand, so I am now convinced that a
true if/else short-circuiting operator is not needed (only about
once every 5,000 lines or so) while an iff()-like builtin function
is much more likely to be appropriate for most cases.

I am about +0.5 for iff() and about -0.7 for the if/else expression.

Andrew
da...@dalkescientific.com


Andrew Dalke

unread,
Feb 10, 2003, 3:56:14 PM2/10/03
to
Dave Brueck

> Several of the previous examples have already illustrated this:
>
> z = iif(x, x.getPref(), 'Not specified')
>
> is broken without short-circuiting.

Indeed. And my best meta-analysis of the code analysis done by
me and others suggests that this form is needed about once every
5,000 lines of code, while a non-short-circuiting function would be
used much more frequently. (I didn't do the analysis of the uses
if an iff() statement, but based on the other results it would be
at least 1 per 1,000 lines, and more likely more often than that,
so my educated guess is about 1 every 400 lines or so.)

Andrew
da...@dalkescientific.com


Andrew Dalke

unread,
Feb 10, 2003, 3:58:31 PM2/10/03
to
Harvey Thomas:

> x = calc(1, iif(cond, resource_intensive_1(), resource_intensive_2()))
>
> In the second case both resource_intensive_1() and resource_intensive_2()
> are evaluated. There is of course the possibility of undesired
side-effects.
>
> You can warn people to not use iif for such cases, but you won't stop it
being used wrongly.

True. But 1) this case in real code comes up very rarely (perhaps 1 in
5,000 lines of code, based on my analysis) and 2) who is going to look
at something which looks like a function call and assume that it has
anything
other than function call semantics?

Andrew
da...@dalkescientific.com


Dave Brueck

unread,
Feb 10, 2003, 3:25:00 PM2/10/03
to
On Mon, 10 Feb 2003, Aahz wrote:

> In article <mailman.104489704...@python.org>,
> Dave Brueck <da...@pythonapocrypha.com> wrote:
> >On Mon, 10 Feb 2003, Aahz wrote:
> >> In article <YUP1a.3080$SB2...@nwrddc03.gnilink.net>,
> >> Raymond Hettinger <pyt...@rcn.com> wrote:
> >>>
> >>>I suggest:
> >>>
> >>> cond ?? val1 || val2
> >>
> >> +0.5
> >>
> >> I still have yet to see a clear explanation of why short-circuit is
> >> necessary
> >
> >Short-circuit evaluation is never "necessary" in _any_ language - it's
> >just very, very useful sometimes. Python's 'and' operator doesn't _have_
> >to be a short-circuit operator, but it's far more useful because it is.
>
> "Far more useful", eh? You need to argue that, not just claim it.

Why should 'and' and 'or' compound expressions be short-circuited but not
'if' expressions? It should be short-circuiting for consistency's sake,
not to mention being more useful.

If the functionality can be exactly emulated with a function, then the
utility of the new feature pretty much drops to zero (and my vote would
swing from +1 to -1). The very fact that people _don't_ just write a
little function (something far easier and less time consuming than, say,
arguing in favor of this PEP) is at least some indication that it's judged
to be worthwhile, even if how worthwhile can't be quanitifed with hard
numbers, or even if it's not very worthwhile to you.

Also, the usefulness of short-circuiting has been shown in several
realistic examples already, so there's little point in repeating them
again and again - to _you_ they just don't seem important or you're simply
ignoring them. For example, early on Michael Chermside gave one example,
you gave a broken counter-example, and Tim corrected you, but point of
Michael's example was still valid even though you never continued the
thread (it was a case where you want to call a method of an object but you
have to check for None first).

To _me_ it is important because I have run into and continue to run into
this same scenario and I find that, without a conditional operator, the
language is getting in the way because the code I have to _write_ doesn't
synch up very well with what I _mean_ (because what I mean is more
accurately conveyed by a conditional expression).

-Dave

David Eppstein

unread,
Feb 10, 2003, 2:16:54 PM2/10/03
to
On 2/10/03 7:36 PM +0100 holger krekel <py...@devel.trillke.net> wrote:
>> My feeling is that the reason for short circuiting isn't so much because
>> of side effects (I think we should try to keep expressions as free of
>> side effects as possible) but because one or both of the two sides may
>> be undefined and raise an exception if the guard condition is not met.
>
> right. in which case learning about and/or (which you have to anyway)
> often helps. Because of the "y is false" problem in "x and y or z"
> there are some cases where it doesn't fit. Do we have real code
> examples for them?

I posted one several hundred messages back:
cols[i] if i >= 0 else None

It's from real code, an example where the and/or trick fails because you
don't know the truth status of cols[i], and an example where the guard
might serve to prevent an array out of bounds exception.

holger krekel

unread,
Feb 10, 2003, 3:02:40 PM2/10/03
to
David Eppstein wrote:
> On 2/10/03 7:36 PM +0100 holger krekel <py...@devel.trillke.net> wrote:
> >
> > right. in which case learning about and/or (which you have to anyway)
> > often helps. Because of the "y is false" problem in "x and y or z"
> > there are some cases where it doesn't fit. Do we have real code
> > examples for them?
>
> I posted one several hundred messages back:
> cols[i] if i >= 0 else None
>
> It's from real code, an example where the and/or trick fails because you
> don't know the truth status of cols[i], and an example where the guard
> might serve to prevent an array out of bounds exception.

ok. I think i have seen that before but also thought
that list/tuple show grow a 'get' method (parallel to
the dict.__getitem__ / dict.get pair).

And i thought why would someone really need to do this
check? Either you allow negative indices (which work on
list/tuples) or you don't in which case you might like
to get into some error-path anyway. How do you get
to 'i<0' anyway?

Apart from this specific example your general perception is interesting ...

> >> My feeling is that the reason for short circuiting isn't so much because
> >> of side effects (I think we should try to keep expressions as free of
> >> side effects as possible) but because one or both of the two sides may
> >> be undefined and raise an exception if the guard condition is not met.

This reinforces an earlier thought about PEP-308 alternatives,
which might read as follows:

cols[i] except IndexError: None

Beeing able to deal with exceptions within expressions like this
would not obsolete other expressions and is unlikely to obfuscate code.

It feels more pythonic to me because it avoids the "look before you
leap" idiom, i.e. you don't have to know anything specific about
your keys and do checks to them. Just try and define the exceptional
result.

regards,

holger

holger krekel

unread,
Feb 10, 2003, 3:11:40 PM2/10/03
to
Andrew Koenig wrote:
> holger> right. in which case learning about and/or (which you have to
> holger> anyway) often helps. Because of the "y is false" problem in
> holger> "x and y or z" there are some cases where it doesn't fit. Do
> holger> we have real code examples for them?
>
> Yes -- as I've noted elsewhere in this discussion, Lib/unittest.py
> actually contains a (minor) bug because it uses and/or where it
> doesn't fit. The code is on lines 618-619:
>
> self.stream.writeln("Ran %d test%s in %.3fs" %
> (run, run == 1 and "" or "s", timeTaken))

I answered on one of the threads you posted it on.
Similar "mix-up" accidents might also happen with PEP-308-syntax.
IMO ternary operators generally lead to mixups. That's probably
because we all think so binary.

regards,

holger


--
The world is divided into 10 kinds of people. Those who
can count binary numbers and those who don't.

Dave Brueck

unread,
Feb 10, 2003, 3:35:36 PM2/10/03
to
On Mon, 10 Feb 2003, holger krekel wrote:

> > Short-circuit evaluation is never "necessary" in _any_ language - it's
> > just very, very useful sometimes. Python's 'and' operator doesn't _have_
> > to be a short-circuit operator, but it's far more useful because it is.
> >

> > > and therefore iif() unreasonable.


> >
> > Several of the previous examples have already illustrated this:
> >
> > z = iif(x, x.getPref(), 'Not specified')
> >
> > is broken without short-circuiting.
>

> yes, but it is easily written with an and-expression
>
> z = not x and 'Not specified' or x.getPref()

Yikes! The above line of code is a great argument _in favor of_
if-expressions on the basis of readability and maintainability. I couldn't
encourage anyone to use that form.

> and a ternary op would simply add another possibility.

...and hopefully deprecate the usage of your above example, the "simulated
conditional expression".

-Dave

Dave Brueck

unread,
Feb 10, 2003, 5:09:44 PM2/10/03
to
On Mon, 10 Feb 2003, holger krekel wrote:

> > > > z = iif(x, x.getPref(), 'Not specified')
> > > >
> > > > is broken without short-circuiting.
> > >
> > > yes, but it is easily written with an and-expression
> > >
> > > z = not x and 'Not specified' or x.getPref()
> >
> > Yikes! The above line of code is a great argument _in favor of_
> > if-expressions on the basis of readability and maintainability. I couldn't
> > encourage anyone to use that form.
>

> It's the "inverse" of
>
> z = obj.method() if hasattr(obj, 'method') else None
>
> which i consider dubious compared to
>
> z = hasattr(obj, 'method') and obj.method()

No, now the functionality has changed from returning 'Not specified' to
None. Besides, it's not just a matter of whether or not the same
functionality can be produced using a different approach, it's also about
expressing intent of the code and it's readability. For example, if I were
hunting for a bug in code that used your "not x and ..." example above,
realistically I'd slow down and review that piece over and over again each
time as it's not that obvious what is happening there (to me at least).

> > > and a ternary op would simply add another possibility.
> >
> > ...and hopefully deprecate the usage of your above example, the "simulated
> > conditional expression".
>

> citing from my last mail:


>
> and a ternary op would simply add another possibility.

Right, I think that's the difference between our two views. IMO, the
conditional operator would *supercede* the "simulated" conditional
expressions. So you don't end up with two "valid" possibilities - you end
up with the normal way to do it and the more hacky way to do it. See, I
regard the conditional operator as something that is missing from the
language, so by adding it a hole is filled so the workaround doesn't need
to be used anymore (yes, old code will still have it, but so what? I
still have old code laying around that imports the string module). It's
the same as with any other feature that was once missing but gets added.

> Even if the old way is bad it will be useful in other situations
> Thus you still have two constructs. In some cases PEP-308 is better,
> in others the and-idiom. But don't forget that *both* will be abused.

I understand that both have the potential for abuse, but to me the old way
_is_ an abuse. To me this is a readable and clear idiom:

x = a or b

as is this:

x = a and b

but going beyond that in terms of complexity and relying on implicit
precedence rules (instead of grouping with parentheses) is much less
obvious and easier to screw up.

Just my two cents,
-Dave

Andrew Dalke

unread,
Feb 10, 2003, 4:06:53 PM2/10/03
to
Gustavo <sism...@hebmex.com>:

> My question is "why leave it half-done?"
>
> Why create a simple builtin function which doesn't do
> short circuiting and then resort to half-baked hacks
> when you do need it, when here's the chance to do it
> fully and have a sanctioned short-circuiting ternary
> operator, usable in all the cases the builtin would
> work, and then some.

Because short-circuiting isn't needed often (perhaps 1 in 5,000
lines of code) so it isn't useful to make yet another language
construct, with all the difficulties in parsing, interpretation, etc.,
when the vast majority of cases (perhaps 1 in 400 lines) can
be handled with a simple function that introduces no new
ideas to the language.

Note that if you accept that people who really want a ternary
if/else operator can sometimes live with

cond and expr1 or expr2

then the only time an if/else operator is needed is for cases
when 'expr1' may be a false value. And that is (according
to Tim Peter's analysis of the Python library code) even
more rare, with a frequency I would estimate of about 1
use in 5 or rarer.

So should we introduce a new idiom to Python which
will only need to be used about once every 25,000 lines
of code, compared to an iff() builtin which will likely
be used about once every 400 lines and doesn't introduce
new fundamental ideas to the language?

Others would argue that a simple ternary if/else operator
is too limited and that it should support easy chaining;
an n-ary if/elif/else statement. So they might argue that
your propose is still only "half-done."

Andrew
da...@dalkescientific.com

Andrew Dalke

unread,
Feb 10, 2003, 4:48:32 PM2/10/03
to
Dave Brueck:

> If the functionality can be exactly emulated with a function, then the
> utility of the new feature pretty much drops to zero (and my vote would
> swing from +1 to -1). The very fact that people _don't_ just write a
> little function (something far easier and less time consuming than, say,
> arguing in favor of this PEP) is at least some indication that it's judged
> to be worthwhile, even if how worthwhile can't be quanitifed with hard
> numbers, or even if it's not very worthwhile to you.

I don't write a function because there's no good name for it.
"Good name" defined as "something which isn't a dialect specific
to my code."

Were there a suggestion for an "ifelse()" builtin, then there would
be a good name.

> Also, the usefulness of short-circuiting has been shown in several
> realistic examples already,

Indeed, and I have tried to point out that the frequency of that
use is, in actual code, quite low.

> To _me_ it is important because I have run into and continue to run into
> this same scenario and I find that, without a conditional operator, the
> language is getting in the way because the code I have to _write_ doesn't
> synch up very well with what I _mean_ (because what I mean is more
> accurately conveyed by a conditional expression).

Could you post, say, 5 examples where you would use this in
you code and provide broader context that would let us understand
the usefulness of a short-circuiting if/else expression over, say,
other existing Python idioms or a (still hypothetical) "ifelse()" function?

This would provide useful real-world context for an if/else expression,
to counter the numbers I found which suggest that a true
short-circuiting if/else expression is only needed roughly once
every 5,000 lines of Python code or so.

Andrew
da...@dalkescientific.com


Anders J. Munch

unread,
Feb 10, 2003, 4:39:48 PM2/10/03
to
"Andrew Dalke" <ada...@mindspring.com> skrev i en meddelelse

>
> Because short-circuiting isn't needed often (perhaps 1 in 5,000
> lines of code) so it isn't useful to make yet another language
> construct, with all the difficulties in parsing, interpretation, etc.,
> when the vast majority of cases (perhaps 1 in 400 lines) can
> be handled with a simple function that introduces no new
> ideas to the language.

Short-circuiting was useful in the other 99.2% also: It relieved the
programmer from having to consider whether redundantly evaluating the
unused case would be ok.

- Anders

Paul Rudin

unread,
Feb 10, 2003, 12:03:14 PM2/10/03
to
>>>>> "Aahz" == Aahz <aa...@pythoncraft.com> writes:

Aahz> In article <YUP1a.3080$SB2...@nwrddc03.gnilink.net>,


Aahz> Raymond Hettinger <pyt...@rcn.com> wrote:
>> I suggest:
>>
>> cond ?? val1 || val2

Aahz> +0.5

Aahz> I still have yet to see a clear explanation of why
Aahz> short-circuit is necessary...

Because computing the unwanted branch might be expensive or might
modify state, or both.

--
Just imagine you're entering a state-of-the-art CAR WASH!!

Dave Brueck

unread,
Feb 10, 2003, 5:26:44 PM2/10/03
to

Yes, I've read with interest your analysis - thanks for doing it.

Adding a new builtin (for the non-short-circuiting version) would get a -1
from me because (1) it would introduce inconsistencies - you have a
pseudo-conditional operator that works a lot of the time but occasionally
bites you if you forget and (2) I already can, and do, add little
"utility" functions all the time as needed so having Python ship it for me
doesn't really add any value.

In C there are lots of people who never use it but for all we know it's
because the language they used before C didn't have one either.

-Dave

David Eppstein

unread,
Feb 10, 2003, 3:52:56 PM2/10/03
to
On 2/10/03 9:02 PM +0100 holger krekel <py...@devel.trillke.net> wrote:
>> I posted one several hundred messages back:
>> cols[i] if i >= 0 else None
>>
>> It's from real code, an example where the and/or trick fails because you
>> don't know the truth status of cols[i], and an example where the guard
>> might serve to prevent an array out of bounds exception.
>
> ok. I think i have seen that before but also thought
> that list/tuple show grow a 'get' method (parallel to
> the dict.__getitem__ / dict.get pair).

cols.get(i,None) would do the wrong thing if i==-1 -- I really want None,
not the last item in cols, for this case.

> And i thought why would someone really need to do this
> check? Either you allow negative indices (which work on
> list/tuples) or you don't in which case you might like
> to get into some error-path anyway. How do you get
> to 'i<0' anyway?

It's a flag value to distinguish a "select all" menu item from the menu
items referring to individual columns.

> This reinforces an earlier thought about PEP-308 alternatives,
> which might read as follows:
>
> cols[i] except IndexError: None

Again, not good, i==-1 doesn't cause the IndexError unless cols is empty.

What would work in my case (since i<0 always ends up being exactly -1)
would be to copy the cols array, append None to the copy, and then use
cols[i] without checks. I happen to think that would be more obscure than
the if-then-else code I've been using.

holger krekel

unread,
Feb 10, 2003, 5:28:11 PM2/10/03
to
David Eppstein wrote:
> On 2/10/03 9:02 PM +0100 holger krekel <py...@devel.trillke.net> wrote:
> >> I posted one several hundred messages back:
> >> cols[i] if i >= 0 else None
> >>
> >> It's from real code, an example where the and/or trick fails because you
> >> don't know the truth status of cols[i], and an example where the guard
> >> might serve to prevent an array out of bounds exception.
> >
> > ok. I think i have seen that before but also thought
> > that list/tuple show grow a 'get' method (parallel to
> > the dict.__getitem__ / dict.get pair).
>
> cols.get(i,None) would do the wrong thing if i==-1 -- I really want None,
> not the last item in cols, for this case.

ok.

> > And i thought why would someone really need to do this
> > check? Either you allow negative indices (which work on
> > list/tuples) or you don't in which case you might like
> > to get into some error-path anyway. How do you get
> > to 'i<0' anyway?
>
> It's a flag value to distinguish a "select all" menu item from the menu
> items referring to individual columns.

i see.

When i had situations like this I rewrote it to get the special "select all"
value not interfere with usual list/tuple-index semantics. E.g. using a
dummy-class for "select_all" rather than reusing an otherwise valid key index.

> > This reinforces an earlier thought about PEP-308 alternatives,
> > which might read as follows:
> >
> > cols[i] except IndexError: None
>
> Again, not good, i==-1 doesn't cause the IndexError unless cols is empty.

right. with my above "class select_all: pass" this would work nicely, though.

> What would work in my case (since i<0 always ends up being exactly -1)
> would be to copy the cols array, append None to the copy, and then use
> cols[i] without checks. I happen to think that would be more obscure than
> the if-then-else code I've been using.

Sure. But I'd rather have my co-coders think about easier ways rather
having to understand ternary operations often. Had i seen your above code

cols[i] if i >= 0 else None

just on its own i would be puzzled (which i was). May i ask
you to show the complete function where this came from?

thanks for your patience (if any is left :-),

holger

holger krekel

unread,
Feb 10, 2003, 3:29:00 PM2/10/03
to
Dave Brueck wrote:
> On Mon, 10 Feb 2003, holger krekel wrote:
>
> > > Short-circuit evaluation is never "necessary" in _any_ language - it's
> > > just very, very useful sometimes. Python's 'and' operator doesn't _have_
> > > to be a short-circuit operator, but it's far more useful because it is.
> > >
> > > > and therefore iif() unreasonable.
> > >
> > > Several of the previous examples have already illustrated this:
> > >
> > > z = iif(x, x.getPref(), 'Not specified')
> > >
> > > is broken without short-circuiting.
> >
> > yes, but it is easily written with an and-expression
> >
> > z = not x and 'Not specified' or x.getPref()
>
> Yikes! The above line of code is a great argument _in favor of_
> if-expressions on the basis of readability and maintainability. I couldn't
> encourage anyone to use that form.

It's the "inverse" of

z = obj.method() if hasattr(obj, 'method') else None

which i consider dubious compared to

z = hasattr(obj, 'method') and obj.method()

> > and a ternary op would simply add another possibility.
>
> ...and hopefully deprecate the usage of your above example, the "simulated
> conditional expression".

citing from my last mail:

and a ternary op would simply add another possibility.

Even if the old way is bad it will be useful in other situations


Thus you still have two constructs. In some cases PEP-308 is better,
in others the and-idiom. But don't forget that *both* will be abused.

holger

holger krekel

unread,
Feb 10, 2003, 5:58:15 PM2/10/03
to
Dave Brueck wrote:
> On Mon, 10 Feb 2003, holger krekel wrote:
>
> > > > > z = iif(x, x.getPref(), 'Not specified')
> > > > >
> > > > > is broken without short-circuiting.
> > > >
> > > > yes, but it is easily written with an and-expression
> > > >
> > > > z = not x and 'Not specified' or x.getPref()
> > >
> > > Yikes! The above line of code is a great argument _in favor of_
> > > if-expressions on the basis of readability and maintainability. I couldn't
> > > encourage anyone to use that form.
> >
> > It's the "inverse" of
> >
> > z = obj.method() if hasattr(obj, 'method') else None
> >
> > which i consider dubious compared to
> >
> > z = hasattr(obj, 'method') and obj.method()
>
> No, now the functionality has changed from returning 'Not specified' to
> None.

I wasn't explicit enough. My "inverse" was meant as a case where
the expr-if-else syntax can lead to "Yikes!".

> Besides, it's not just a matter of whether or not the same
> functionality can be produced using a different approach, it's also about
> expressing intent of the code and it's readability. For example, if I were
> hunting for a bug in code that used your "not x and ..." example above,
> realistically I'd slow down and review that piece over and over again each
> time as it's not that obvious what is happening there (to me at least).

I think every ternary operator slows down human parsing. For that matter

if x:
z = x.getPref()
else:
z = "not specified"

parses the fastest and is easily understood. Sure it isn't optimal
with respect to the number of lines but that was never a goal with python.

> > > > and a ternary op would simply add another possibility.
> > >
> > > ...and hopefully deprecate the usage of your above example, the "simulated
> > > conditional expression".
> >
> > citing from my last mail:
> >
> > and a ternary op would simply add another possibility.
>

> Right, I think that's the difference between our two views. IMO, the
> conditional operator would *supercede* the "simulated" conditional
> expressions. So you don't end up with two "valid" possibilities - you end
> up with the normal way to do it and the more hacky way to do it.

And thus might not even learn (or care) that 'and' lets your return
something other than a boolean.

> [...]


> > Even if the old way is bad it will be useful in other situations
> > Thus you still have two constructs. In some cases PEP-308 is better,
> > in others the and-idiom. But don't forget that *both* will be abused.
>

> I understand that both have the potential for abuse, but to me the old way
> _is_ an abuse. To me this is a readable and clear idiom:
>
> x = a or b
>
> as is this:
>
> x = a and b

but this might often not be used anymore in a PEP-308 world.
This and/or behaviour is unfamiliar for many whereas the ternary
op is not. The abuses of the latter might very well reach the
same quantity than the problem they try to cure.

> but going beyond that in terms of complexity and relying on implicit
> precedence rules (instead of grouping with parentheses) is much less
> obvious and easier to screw up.

Statements on easy (i.e. non-ternary) expressions are my favorite :-)

holger

James J. Besemer

unread,
Feb 10, 2003, 6:09:58 PM2/10/03
to

Aahz wrote:

> That's still not addressing my point: how often is short-circuit
> evaluation needed?

This is pure rhetoric. It's impossible to answer.

Otherwise, tell us what is is the "correct" answer? 10% of the time? 1%?
0.1%? There is no correct answer.

How often are list comprehensions needed? Booleans needed?

Python already wisely recognizes the need for short-circuit within
expressions. But and/or is not powerful enough.

> That's the *only* reason to consider conditional
> expressions rather than a new builtin conditional function.

Not true, as I and others have explained at length elsewhere. Readability
and maintainability are SERVED by factoring out common sub-expressions from
the more verbose forms:

if condition1:
if condition2
targetVar1 = result1
else:
targetVarl = result2 # hidden BUG!!
else:
targetVar1 = result3


--jb


--
James J. Besemer 503-280-0838 voice
2727 NE Skidmore St. 503-280-0375 fax
Portland, Oregon 97211-6557 mailto:j...@cascade-sys.com
http://cascade-sys.com

Dave Brueck

unread,
Feb 10, 2003, 7:17:45 PM2/10/03
to
On Mon, 10 Feb 2003, Andrew Dalke wrote:

> > Also, the usefulness of short-circuiting has been shown in several
> > realistic examples already,
>
> Indeed, and I have tried to point out that the frequency of that
> use is, in actual code, quite low.

Perhaps, but maybe the fact that it is non-zero is what troubles me.
Python has short-circuiting logical operators and I use them in cases
where that matters _and_ when it doesn't, and I used C's conditional
operator in cases where short-circuiting mattered _and_ when it didn't, so
it's likely that I would intend to use it in Python the same way, but the
builtin-function way would be a half-way solution so I'd probably steer
clear from it altogether just to be safe.

> > To _me_ it is important because I have run into and continue to run into
> > this same scenario and I find that, without a conditional operator, the
> > language is getting in the way because the code I have to _write_ doesn't
> > synch up very well with what I _mean_ (because what I mean is more
> > accurately conveyed by a conditional expression).
>
> Could you post, say, 5 examples where you would use this in
> you code and provide broader context that would let us understand
> the usefulness of a short-circuiting if/else expression over, say,
> other existing Python idioms or a (still hypothetical) "ifelse()" function?

Well, to me this feels like a trap because you are already fully aware of
when some people consider it useful and expressive, but in your opinion
it's still not worth it. My view obviously differs - even though, like
you, I've been programming in Python a long while, I still miss having it,
and I know that in some of those cases in which I had it they would
require short-circuiting behavior.

I do not disagree that in many uses of the conditional operator
short-circuiting would not matter. But, the cases in which it _does_
matter are some of the most useful to me. Furthermore, setting
short-circuiting aside, calling a separate function to make the binary
choice just _seems_ wrong - unPythonic and kinda like having to call if()
for normal if-statements - it just feels like a lot of extra work to
express a very simple thought, so much so that I'd probably handle it I do
now: grumble quietly about how I wish we had a conditional operator, and
then code it up in a way that doesn't quite capture what I mean but is
good enough.

I am in favor of the PEP because of *both* the short-circuiting *and* code
readability - it expresses *exactly* the thought I'm really trying to
convey in those instances that I use it, whereas

if c:
z=5
else:
z=6

doesn't quite do it, neither does:

z=6
if c:
z=5

> This would provide useful real-world context for an if/else expression,

Having said the above:

The access-a-member-of-a-variable-if-not-None idiom seems to be the one I
encounter most often, e.g.

z = x.foo if x else -1

But even when I know a variable isn't None I also see similar variants
with data transmission/loading:

z = x.size() if x.loaded or '(Loading...)'

As mentioned elsewhere, this form is a way of expressing intended or
preferred or "normal" execution - it really expresses the "conditional"
nature - it's a conditional assignment in this case.

One other case I encounter less often deals with recalculation of cached
values, although depending on the specific context recalculation may occur
invisibly to the caller. In cases where it's not, then the check is
against some cache freshnes value. The same holds true for expiring
content:

resp = x.data if x.isFresh() else GetStaleResponse()

I am fully aware that any of these can be rewritten to another way -
that's not the issue. For me personally it's a matter of the most clear
and direct way to accomplish what I'm trying to do, other approaches feel
like the language is getting in the way.

In addition to the short-circuit-required type of uses, there are many
more in which it's just really clear and convenient for me to have such a
construct, but having to tread lightly and use it only when
short-circuiting is definitely not required would be enough of an
annoyance to not bother with a conditional function at all.

> to counter the numbers I found which suggest that a true
> short-circuiting if/else expression is only needed roughly once
> every 5,000 lines of Python code or so.

I believe too much has been concluded from these stats - I agree that it
would be great to have some real numbers but can we really infer what
people _would_ have done if a different construct were available,
especially when it is a matter of preference or experience?

Did you also include the use case I listed above (assign then check then
assign again - yeah, it's not short-circuiting, but is often a potential
use of conditional operators)?

Even though it's known to someone in C doesn't necessarily mean they would
give it an honest try, either - it's common around here to kindly
encourage people to "think Pythonically" so maybe people who didn't use it
in C were still thinking in their previous language.

-Dave

James J. Besemer

unread,
Feb 10, 2003, 6:17:59 PM2/10/03
to

sism...@hebmex.com wrote:

> My question is "why leave it half-done?"
>
> Why create a simple builtin function which doesn't do
> short circuiting and then resort to half-baked hacks
> when you do need it, when here's the chance to do it
> fully and have a sanctioned short-circuiting ternary
> operator, usable in all the cases the builtin would
> work, and then some.

Exactly.

Specious arguments that short-circuiting is not needed or seldom needed are
thinly disguised restatements that cond-if is not needed.

Regards

James J. Besemer

unread,
Feb 10, 2003, 6:15:28 PM2/10/03
to

Andrew Dalke wrote:
> Raymond Hettinger
>
>>># Example where all three reasons apply
>>>data = isinstance(source, str) ?? source.readlines() ||
>>
>>source.split()
>>
>>That should have been:
>> isinstance(source, file)


> Err, that should have been
>
> [ spelled out long-hand ]

Now you're being unreasonable.

You were asked for an example where short-circuit would be necessary and this
is a well-intentioned, legitamet illustration.

The fact (as you point out and WE ALL KNOW) that it can be rewritten the
other way does not materially add to the discussion.

James J. Besemer

unread,
Feb 10, 2003, 6:12:15 PM2/10/03
to

Aahz wrote:
> Dave Brueck <da...@pythonapocrypha.com> wrote:

>>Short-circuit evaluation is never "necessary" in _any_ language - it's
>>just very, very useful sometimes. Python's 'and' operator doesn't _have_
>>to be a short-circuit operator, but it's far more useful because it is.
>
>

> "Far more useful", eh? You need to argue that, not just claim it.

This has been asked and answered many times.

Or are you saying Python would be better if it's 'and' and 'or' did not short
circuit?

James J. Besemer

unread,
Feb 10, 2003, 6:21:34 PM2/10/03
to

Andrew Dalke wrote:
> Andrew Koenig:
>
>>Yes -- as I've noted elsewhere in this discussion, Lib/unittest.py
>>actually contains a (minor) bug because it uses and/or where it
>>doesn't fit. The code is on lines 618-619:
>>
>> self.stream.writeln("Ran %d test%s in %.3fs" %
>> (run, run == 1 and "" or "s", timeTaken))
>
>
> And I've noted elsewhere (so no need to followup on this thread)
> that from that snippet it appear that the person who wrote this
> has more exprience in using other languages (hence the strange
> use of 'writeln') than Python, so that this is perhaps not the best
> indicator of an apropriate Python solution.

Doh.

You silly.

The POINT is that the example contains yet another glaring BUG.

In trusted Python library code.

--jb

> On the other hand, it suggests that an if/else expression would
> make for fewer mistakes caused by people with experience in
> if/else from other languages.

Yes, a forceful case.

David Eppstein

unread,
Feb 10, 2003, 6:39:44 PM2/10/03
to
On 2/10/03 11:28 PM +0100 holger krekel <py...@devel.trillke.net> wrote:
>> It's a flag value to distinguish a "select all" menu item from the menu
>> items referring to individual columns.
>
> i see.
>
> When i had situations like this I rewrote it to get the special "select
> all" value not interfere with usual list/tuple-index semantics. E.g.
> using a dummy-class for "select_all" rather than reusing an otherwise
> valid key index.
>
>> > This reinforces an earlier thought about PEP-308 alternatives,
>> > which might read as follows:
>> >
>> > cols[i] except IndexError: None
>>
>> Again, not good, i==-1 doesn't cause the IndexError unless cols is empty.
>
> right. with my above "class select_all: pass" this would work nicely,
> though.

Cocoa NSPopUpButton's indexOfSelectedItem method doesn't return non-numeric
values.

> Sure. But I'd rather have my co-coders think about easier ways rather
> having to understand ternary operations often. Had i seen your above
> code
>
> cols[i] if i >= 0 else None
>
> just on its own i would be puzzled (which i was). May i ask
> you to show the complete function where this came from?

Not that I make any claim of having polished this to jewel-like perfection,
but here it is. It's part of the controller for the Find dialog in a
table-editing application. The input data structures are:
self.doc.columns() -- a list of strings used as dict keys
self.doc.rows() -- a list of dicts keyed by the columns
contains, beginsWith, endsWith, exactMatch -- localized string compare
routines
self.table -- the controller for the table display
self.column, self.match, self.text -- components of the Find dialog
Note that self.match and self.columns are both pop-up buttons, but accessed
differently because one is static and the other has to be updated when the
self.doc.columns() changes.

def search(self, row, increment):
def matches(row):
if col is not None:
return match(row.get(col, ''), target)
for c in cols:
if match(row.get(c, ''), target):
return 1
return 0

cols = self.doc.columns()
col = self.column.indexOfSelectedItem() - 1
if col < 0:
col = None
else:
col = cols[col]

match = self.match.selectedItem().tag()
match = (contains, beginsWith, endsWith, exactMatch)[match]
target = self.text.stringValue()
rows = self.doc.rows()
while 1:
row += increment
if row < 0 or row >= len(rows):
return 0
if matches(rows[row]):
self.table.setSelectedLine_(row)
return 1

Looking at it again, it is possible to simplify this, in a way that gets
rid of the implicit ternary, allowing the subroutine to be more easily
folded into the main routine:

def search(self, row, increment):
cols = self.doc.columns()
col = self.column.indexOfSelectedItem() - 1
if col >= 0:
cols = [cols[col]]
match = self.match.selectedItem().tag()
match = (contains, beginsWith, endsWith, exactMatch)[match]
target = self.text.stringValue()
rows = self.doc.rows()
while 1:
row += increment
if row < 0 or row >= len(rows):
return 0
for c in cols:
if match(rows[row].get(c, ''), target):
self.table.setSelectedLine_(row)
return 1

But, clearly, the existence or nonexistence of a ternary operator had
nothing to do with my ability to find this simplification -- I already had
working code for this problem, so had little motivation to work harder on
simplifying it until you asked me to post it.

Andrew Dalke

unread,
Feb 10, 2003, 7:35:27 PM2/10/03
to
James J. Besemer:

> Andrew Dalke wrote:
> > Raymond Hettinger
> > ....

> > Err, that should have been
> >
> > [ spelled out long-hand ]

> Now you're being unreasonable.

No, I'm not being unreasonable. Raymond used

data = isinstance(source, file) ?? source.readlines() ||
source.split()

My post was not commenting about the use of the ?? || syntax,
it was saying that explicit type checking should not be used for
this case.

Specifically, don't check for a file instance, check to see if it supports
a 'readlines'. As written, it prevents me from using a StringIO class
or anything else which implements 'readlines.'

At best, do the type check only for the most restrictive case
(which is a string) rather than the least restrictive case (a file-like
object).

The fact that I wrote my objection using the traditional if/else has
nothing to do with the point of the matter.

> You were asked for an example where short-circuit would be necessary and
this
> is a well-intentioned, legitamet illustration.
>
> The fact (as you point out and WE ALL KNOW) that it can be rewritten the
> other way does not materially add to the discussion.

The test should have been, in his parlance,

data = hasattr(source, "readlines") ?? source.readlines() ||
source.split()

Even with that case, I would rather not get that property twice,
so, using Alex's clarification of my example, the best solution is

try:
readlines = source.readlines
except AttributeError:
data = source.split()
else:
data = readlines()

Therefore, even though I was not really commenting on the use
of an if/else expression idiom, it happens that this example is not
legitamet .. legtiment, .. legit-whatever.

Andrew
da...@dalkescientific.com

Andrew Dalke

unread,
Feb 10, 2003, 7:53:35 PM2/10/03
to
James J. Besemer:
> Aahz:

> > That's still not addressing my point: how often is short-circuit
> > evaluation needed?
>
> This is pure rhetoric. It's impossible to answer.
>
> Otherwise, tell us what is is the "correct" answer? 10% of the time? 1%?
> 0.1%? There is no correct answer.

Estimated at over once every 5,000 lines, but likely even lower
rates. See other posts of mine for why.

> How often are list comprehensions needed? Booleans needed?

I have not done the analysis. When the list comprehensions
addition was discussed, there were some ad hoc usability
tests done to evalute the different syntaxes. There were also
dicussions about how it is used in other languages. Now that
they exist, I used them, but with strict guidelines (no embedded
list comps, no "for x in .. for y in ..." constructs, no term may
exceed more than one line, so a 3 line max). They ended
up replacing functions which were hard to name and hard
to understand, like

def get_list_attr(dataset, attr):
results = []
for x in dataset:
results.append(getattr(x, attr))
return results


For me, booleans were not new syntax they were simply
new built-in objects which worked in the same framework as
the existing code. There were some changes to how
comparisons are done, but all were done in a backwards
compatiable way. In addition, I needed booleans for some
projects (eg, to express configuration options) so having a
commong spelling of True/False helped simplify bad code.
The objections to adding bool were deemed minor enough
by our Fearless BDFL.


> Python already wisely recognizes the need for short-circuit within
> expressions. But and/or is not powerful enough.
>
> > That's the *only* reason to consider conditional
> > expressions rather than a new builtin conditional function.
>
> Not true, as I and others have explained at length elsewhere. Readability
> and maintainability are SERVED by factoring out common sub-expressions
from
> the more verbose forms:
>
> if condition1:
> if condition2
> targetVar1 = result1
> else:
> targetVarl = result2 # hidden BUG!!
> else:
> targetVar1 = result3

Such variable naming schemes, of course, are also
deemed unwise. In addition, it turns out that most code
looks like this

need_delete = 0


if condition1:
if condition2
targetVar1 = result1
else:

targetVar1 = result2
need_delete = 1
else:
targetVar1 = result3

so that if the original code was written with a set of
embedded if/else expressions, then it would need to be
rewritten (and retested) to add this 'need_delete' flag.

Andrew
da...@dalkescientific.com


Andrew Dalke

unread,
Feb 10, 2003, 7:58:29 PM2/10/03
to
James J. Besemer:

> Doh.
>
> You silly.
>
> The POINT is that the example contains yet another glaring BUG.
>
> In trusted Python library code.

Glaring? No.

With deep side effects? No.

Would an if/else expression have prevented this error? Possibly.
Though there will also be errors in an if/else expression. And
this specific error type 1) would not exist were there an ifelse()
builtin function and 2) was apparantly found and fixed 8 months
ago.

> > On the other hand, it suggests that an if/else expression would
> > make for fewer mistakes caused by people with experience in
> > if/else from other languages.
>
> Yes, a forceful case.

No, a case. I do not deny there are good uses of this PEP
proposal. It's just that there are also consequences of this
expression which suggest that overall it is inappropriate for
Python.

Andrew
da...@dalkescientific.com


holger krekel

unread,
Feb 10, 2003, 7:16:59 PM2/10/03
to
David Eppstein wrote:
> On 2/10/03 11:28 PM +0100 holger krekel <py...@devel.trillke.net> wrote:
> >
> > When i had situations like this I rewrote it to get the special "select
> > all" value not interfere with usual list/tuple-index semantics. E.g.
> > using a dummy-class for "select_all" rather than reusing an otherwise
> > valid key index.
> >

thanks ...



> Looking at it again, it is possible to simplify this, in a way that gets
> rid of the implicit ternary, allowing the subroutine to be more easily
> folded into the main routine:

interesting ...



> def search(self, row, increment):
> cols = self.doc.columns()
> col = self.column.indexOfSelectedItem() - 1
> if col >= 0:
> cols = [cols[col]]

this was exactly what i hoped for when i asked: avoiding
the special cased index (-1) and constructing the list of
all columns (or just with one item) from the start. Thus
you adapt the Cocoa-semantic right where you invoked it
and doesn't let it interfere with python semantics.

> match = self.match.selectedItem().tag()
> match = (contains, beginsWith, endsWith, exactMatch)[match]
> target = self.text.stringValue()
> rows = self.doc.rows()
> while 1:
> row += increment
> if row < 0 or row >= len(rows):
> return 0
> for c in cols:
> if match(rows[row].get(c, ''), target):
> self.table.setSelectedLine_(row)
> return 1
>
> But, clearly, the existence or nonexistence of a ternary operator had
> nothing to do with my ability to find this simplification -- I already had
> working code for this problem, so had little motivation to work harder on
> simplifying it until you asked me to post it.

sure, but

a) would you have reimplemented it with PEP-308 syntax?

b) it doesn't exactly disprove my point that ternary operators
can often be avoided for great justice :-)

cheers,

holger

holger krekel

unread,
Feb 10, 2003, 7:22:03 PM2/10/03
to
James J. Besemer wrote:
>
>
> Andrew Dalke wrote:
> > Andrew Koenig:
> >
> >>Yes -- as I've noted elsewhere in this discussion, Lib/unittest.py
> >>actually contains a (minor) bug because it uses and/or where it
> >>doesn't fit. The code is on lines 618-619:
> >>
> >> self.stream.writeln("Ran %d test%s in %.3fs" %
> >> (run, run == 1 and "" or "s", timeTaken))
> >
> >
> > And I've noted elsewhere (so no need to followup on this thread)
> > that from that snippet it appear that the person who wrote this
> > has more exprience in using other languages (hence the strange
> > use of 'writeln') than Python, so that this is perhaps not the best
> > indicator of an apropriate Python solution.
>
> Doh.
>
> You silly.

This is not a great way to argue. Despite the huge amount of
discussions we have managed to have a rather friendly discussion.
Why do you want to change it?

> The POINT is that the example contains yet another glaring BUG.

As if Andrew doesn't know that. To me it's silly to read his
paragraph as if he was just complaining about 'writeln' and
missed the point.

> In trusted Python library code.

fixed 8 month ago.

holger

David Eppstein

unread,
Feb 10, 2003, 7:43:20 PM2/10/03
to
On 2/11/03 1:16 AM +0100 holger krekel <py...@devel.trillke.net> wrote:
> a) would you have reimplemented it with PEP-308 syntax?

Only to prove a point, or as part of a larger pass of simplification
through the code.
However, had PEP-308 syntax been available I would likely have used it for
this code when I originally wrote it.

> b) it doesn't exactly disprove my point that ternary operators
> can often be avoided for great justice :-)

True...but I think that's just a very special case of a larger theorem that
a lot of code complexity can often be avoided with a little more programmer
thought.

Erik Max Francis

unread,
Feb 10, 2003, 8:24:43 PM2/10/03
to
"James J. Besemer" wrote:

> You were asked for an example where short-circuit would be necessary
> and this
> is a well-intentioned, legitamet illustration.
>
> The fact (as you point out and WE ALL KNOW) that it can be rewritten
> the
> other way does not materially add to the discussion.

Indeed. There are _always_ alternatives, everybody knows that. The
issue is not whether or not there is an expression that fundamentally
cannot be written without the conditional operator, because everybody on
both sides of the debate knows very well that there is no such thing.

That's not the question. The question is whether or not some forms are
more readable with the conditional operator than without it. It's
fundamentally frustrating when people shoot down legitimate examples of
the conditional operator with, "Oh, but you could have done it _this_
way." Well, of _course_ you could have. The question is whether the
conditional form is useful and readable on its own merits.

When people shoot down the max example (e.g., if x > y: x else: y) with
"Well, you should have used max(x, y)!" is utterly frustrating. Of
_course_ it could be written that way. We're not asking whether there's
another way to do it, we're asking whether that is readable on its own
merits. Those who are against the PEP on general principle seem to
never understand this distinction.

--
Erik Max Francis / m...@alcyone.com / http://www.alcyone.com/max/
__ San Jose, CA, USA / 37 20 N 121 53 W / &tSftDotIotE
/ \ Whoever contends with the great sheds his own blood.
\__/ Sa'di
Polly Wanna Cracka? / http://www.pollywannacracka.com/
The Internet resource for interracial relationships.

Paul Rubin

unread,
Feb 10, 2003, 8:25:05 PM2/10/03
to
"Andrew Dalke" <ada...@mindspring.com> writes:
> > Otherwise, tell us what is is the "correct" answer? 10% of the time? 1%?
> > 0.1%? There is no correct answer.
>
> Estimated at over once every 5,000 lines, but likely even lower
> rates. See other posts of mine for why.


Andrew, I keep wondering why you post these statistics. I gather the
low frequency of conditional expressions (CE's) in code that you
examine is supposed to be some kind of evidence that they're not
useful all that frequently. However, empirically, whether they're
useful frequently or not, they're useful often enough that people keep
asking about them and we get these endless threads.

On the other hand, the most valid answer to the argument "well, let's
add them to the language and if you don't like them, then just don't
use them and stop bothering those of us who do" is that we have to
read code written by others, as well as write code ourselves. And we
might be concerned that frequent use of CE's will lead to a lot of
code being confusing and hard-to-read.

In that context, your statistics about low usage frequency seem to say
that adding CE's will both satisfy the people asking for them AND
rarely bother those who don't like them (since they occur so seldom in
C programs).

But if that's the situation, why are you making such a big deal about
the issue? There seem to be three camps here:

1) those who like CE's and want to use them in their own code as a
matter of stylistic preference

2) those who don't like CE's and are concerned about getting confused
by seeing them in other people's code, and

3) your own posts, which seem to statistically argue that seeing
CE's in other people's code will be a rare occurence, yet seem
desperate regardless to keep CE's out of the language.

I thus have to ask: if CE's are so rare, then why does the subject
matter to you? You won't be required to use them in your own code if
they're added. And according to your own statistics, you'll very
seldom have to deal with them in other people's code either.

So I'm sorry, but it really sounds like you're trying to impose your
stylistic preferences on other people without any practical
justification. The other CE opponents' posts don't give that
impression nearly as much.

Erik Max Francis

unread,
Feb 10, 2003, 8:25:43 PM2/10/03
to
Aahz wrote:

> In article <YUP1a.3080$SB2...@nwrddc03.gnilink.net>,


> Raymond Hettinger <pyt...@rcn.com> wrote:
>
> > I suggest:
> >
> > cond ?? val1 || val2
>

> +0.5

Why would this be better than the form (suggested in the PEP) of

cond ? val1 ! val2

(which Guido expressed displeasure over but did not reject out of hand)?

Erik Max Francis

unread,
Feb 10, 2003, 8:28:17 PM2/10/03
to
Andrew Dalke wrote:

> My other comments stand, so I am now convinced that a
> true if/else short-circuiting operator is not needed (only about
> once every 5,000 lines or so) while an iff()-like builtin function
> is much more likely to be appropriate for most cases.

I'm still puzzled over the choice of `iff' for this idea. In maths, it
means "if and only if," which is totally the wrong meaning for an "if
this, otherwise that" function.

Someone else, I believe, suggested `iif', but I _really_ can't see how
that helps.

Erik Max Francis

unread,
Feb 10, 2003, 8:36:59 PM2/10/03
to
Andrew Dalke wrote:

> True. But 1) this case in real code comes up very rarely (perhaps 1
> in
> 5,000 lines of code, based on my analysis) ...

You keep invoking the frequency argument. I don't find it convincing.
How often are Booleans used? metaclasses? generators? list
comprehensions? There are plenty of features in Python that _are
already present_ that are used very rarely. But when they are used,
they do their job with flying colors.

The question is whether or not _when it's used_ it serves its purpose.
You may think that it is never useful, but clearly others don't. Either
way, the frequency argument doesn't get either side anywhere.

A conditional operator or form should be short-circuiting, because it
simply doesn't make sense to go through the trouble of adding one that
doesn't. Everyone knows that a non-short-circuiting conditional
function is utterly _trivial_. Why bother adding it if it doesn't short
circuit, no matter how rare short circuiting is?

Aahz

unread,
Feb 10, 2003, 8:57:06 PM2/10/03
to
In article <mailman.104491869...@python.org>,
James J. Besemer <j...@cascade-sys.com> wrote:

>Aahz wrote:
>>
>> That's the *only* reason to consider conditional
>> expressions rather than a new builtin conditional function.
>
>Not true, as I and others have explained at length elsewhere. Readability
>and maintainability are SERVED by factoring out common sub-expressions from
>the more verbose forms:
>
> if condition1:
> if condition2
> targetVar1 = result1
> else:
> targetVarl = result2 # hidden BUG!!
> else:
> targetVar1 = result3

How is what you're saying here an argument against a conditional
function?

targetVar1 = iif(cond1, iif(cond2, result1, result2), result3)

Seems to me that short-circuit is the *only* reason to dislike iif();
and therefore you need to make your argument on changing the language
(rather than the library) solely on the short-circuit point. That's a
lot tougher, I think.
--
Aahz (aa...@pythoncraft.com) <*> http://www.pythoncraft.com/

Register for PyCon now! http://www.python.org/pycon/reg.html

Tim Peters

unread,
Feb 10, 2003, 7:57:56 PM2/10/03
to
>> In trusted Python library code.

> fixed 8 month ago.

But not backported to the 2.2 branch, despite that it was fixed long before
2.2.2 was released. That's a real bug, but of a different kind. As to the
code bug, if someone wrote a unittest that managed to run exactly one test
(no more, no less), and some impressionable youngster's conception of
singular vs plural was permanently damaged by seeing "1 tests" on the screen
at the end, I encourage them to sue. Not the PSF, though -- I hear
Microsoft has money to spare.


Raymond Hettinger

unread,
Feb 10, 2003, 9:02:27 PM2/10/03
to

"Paul Rubin" <http://phr...@NOSPAM.invalid> wrote in message

> Andrew, I keep wondering why you post these statistics. I gather the
> low frequency of conditional expressions (CE's) in code that you
> examine is supposed to be some kind of evidence that they're not
> useful all that frequently

I find Andrew's statistics to be useful and compelling.
They are my only hesitation about favoring x = c ?? a || b
over iif(c, a, b).


Raymond Hettinger


Aahz

unread,
Feb 10, 2003, 9:02:40 PM2/10/03
to
In article <mailman.1044919572...@python.org>,

James J. Besemer <j...@cascade-sys.com> wrote:
>Aahz wrote:
>> Dave Brueck <da...@pythonapocrypha.com> wrote:
>>>
>>>Short-circuit evaluation is never "necessary" in _any_ language - it's
>>>just very, very useful sometimes. Python's 'and' operator doesn't _have_
>>>to be a short-circuit operator, but it's far more useful because it is.
>>
>> "Far more useful", eh? You need to argue that, not just claim it.
>
>This has been asked and answered many times.

Not yet. So far, I haven't seen a clear justification for making this a
language-level change.

>Or are you saying Python would be better if it's 'and' and 'or' did not
>short circuit?

Not in the slightest. I *am* saying that I think that any code that
depends on short-circuit evaluation probably should have more of a
visual marker.

Aahz

unread,
Feb 10, 2003, 9:05:19 PM2/10/03
to
In article <3E48511...@alcyone.com>,

Erik Max Francis <m...@alcyone.com> wrote:
>Aahz wrote:
>> In article <YUP1a.3080$SB2...@nwrddc03.gnilink.net>,
>> Raymond Hettinger <pyt...@rcn.com> wrote:
>>>
>>> cond ?? val1 || val2
>>
>> +0.5
>
>Why would this be better than the form (suggested in the PEP) of
>
> cond ? val1 ! val2
>
>(which Guido expressed displeasure over but did not reject out of hand)?

Because the extra punctuation calls out more clearly, IMO. Also, I like
the "||" meaning "or".

Alexander Schmolck

unread,
Feb 10, 2003, 9:08:18 PM2/10/03
to
Erik Max Francis <m...@alcyone.com> writes:

> Andrew Dalke wrote:
>
> > True. But 1) this case in real code comes up very rarely (perhaps 1
> > in
> > 5,000 lines of code, based on my analysis) ...
>
> You keep invoking the frequency argument. I don't find it convincing.
> How often are Booleans used? metaclasses? generators? list
> comprehensions? There are plenty of features in Python that _are
> already present_ that are used very rarely. But when they are used,
> they do their job with flying colors.

Frequency * expressivness comes close to measure the usefulness of a
construct. So for something that adds near 0 expressiveness, the frequency
argument is extremely convincing.

alex

Paul Rubin

unread,
Feb 10, 2003, 9:12:35 PM2/10/03
to
"Raymond Hettinger" <vze4...@verizon.net> writes:
> > Andrew, I keep wondering why you post these statistics. I gather the
> > low frequency of conditional expressions (CE's) in code that you
> > examine is supposed to be some kind of evidence that they're not
> > useful all that frequently
>
> I find Andrew's statistics to be useful and compelling.

I think they're interesting and maybe persuasive, but not in the
direction that he seems to want.

James J. Besemer

unread,
Feb 10, 2003, 9:48:31 PM2/10/03
to

Andrew Dalke wrote:

> No, a case. I do not deny there are good uses of this PEP
> proposal.

Yea!

> It's just that there are also consequences of this
> expression which suggest that overall it is inappropriate for
> Python.

Can you enumerate those negative consequences and quantify their cost some how?

James J. Besemer

unread,
Feb 10, 2003, 9:46:16 PM2/10/03
to

holger krekel wrote:
>>Doh.
>>
>>You silly.
>
>
> This is not a great way to argue. Despite the huge amount of
> discussions we have managed to have a rather friendly discussion.
> Why do you want to change it?

I apologize. I meant no disrespect.

Although you and I have had friendly conversations in the past, I see here,
after a hiatus, I assumed a familiarity that was not merited.

Again, I apologize if, in haste, I inadvertantly gave offense.

I humbly beseach you to forgive me.

> As if Andrew doesn't know that. To me it's silly to read his
> paragraph as if he was just complaining about 'writeln' and
> missed the point.

Somebody other than Andrews was complaining about 'writeln'.

Regards

Evan

unread,
Feb 10, 2003, 10:03:08 PM2/10/03
to
Aahz wrote:
> Not yet. So far, I haven't seen a clear justification for making this a
> language-level change.

I doubt that anyone who hasn't used Zope Page Templates extensively will
find this persuasive, but in that realm (where Python expressions are
possible, but statements are not) there has been a fair amount of pain
suffered for lack of a short-circuiting conditional expression.

ZPTs *do* provide a non-short-circuiting "test(cond, t, f)" function,
and when it is insufficient, use of the ugly _ and _ or _ idiom is
required, since otherwise you end up having to write something like:

<tal:x condition="cond">
<tal:x define="global v python:t()" />
</tal:x>
<tal:x condition="not:cond">
<tal:x define="global v python:f()" />
</tal:x>
<p tal:content="v"></p>

...instead of

<p tal:content="python:(if cond: t() else: f())"></p>

As I say, though, non-ZPTer are unlikely to care :-)

Cheers,

Evan @ 4-am

holger krekel

unread,
Feb 10, 2003, 10:05:40 PM2/10/03
to
James J. Besemer wrote:
>
> holger krekel wrote:
> >>Doh.
> >>
> >>You silly.
> >
> >
> > This is not a great way to argue. Despite the huge amount of
> > discussions we have managed to have a rather friendly discussion.
> > Why do you want to change it?
>
> I apologize. I meant no disrespect.
>
> Although you and I have had friendly conversations in the past, I see here,
> after a hiatus, I assumed a familiarity that was not merited.

you didn't say "silly" to me. but excuse is welcome anyway.

> > As if Andrew doesn't know that. To me it's silly to read his
> > paragraph as if he was just complaining about 'writeln' and
> > missed the point.
>
> Somebody other than Andrews was complaining about 'writeln'.

In this thread we just developed? There it was Andrew Dalke, i think.
I think good real-world examples and some statistics can't hurt for
sorting out the situation, btw.

anyway, i try to step back from further PEP-308 discussions for the
time beeing (second try). I just go to sleep that should help.
One last note. This discussion has helped me on several accounts
and especially recognizing that i like python to *not* be an
expression-oriented language. Let nice statements and indentation
do the job so we don't regularly have to stop parsing some
super-clever expressions manually.

regards,

holger

Bengt Richter

unread,
Feb 11, 2003, 12:10:52 AM2/11/03
to
On Mon, 10 Feb 2003 19:37:42 GMT, Andrew Koenig <a...@research.att.com> wrote:

>holger> right. in which case learning about and/or (which you have to
>holger> anyway) often helps. Because of the "y is false" problem in
>holger> "x and y or z" there are some cases where it doesn't fit. Do
>holger> we have real code examples for them?


>
>Yes -- as I've noted elsewhere in this discussion, Lib/unittest.py
>actually contains a (minor) bug because it uses and/or where it
>doesn't fit. The code is on lines 618-619:
>
> self.stream.writeln("Ran %d test%s in %.3fs" %
> (run, run == 1 and "" or "s", timeTaken))
>

with my latest, that would be spelled

self.stream.writeln("Ran %d test%s in %.3fs" %

(run, run == 1 -> "" -> "s", timeTaken))

Regards,
Bengt Richter

Bengt Richter

unread,
Feb 11, 2003, 12:16:42 AM2/11/03
to
On Mon, 10 Feb 2003 10:23:11 -0800 (PST), Dave Brueck <da...@pythonapocrypha.com> wrote:

>On Mon, 10 Feb 2003, Aahz wrote:
>
>> In article <YUP1a.3080$SB2...@nwrddc03.gnilink.net>,
>> Raymond Hettinger <pyt...@rcn.com> wrote:
>> >

>> >I suggest:
>> >
>> > cond ?? val1 || val2

cond -> val1 -> val2

which is short for
cond -> val1 >< True -> val2

which is a two-condition version of
cond -> val1 >< cond2 -> val2 >< cond3 -> val3 >< True -> valdefault

>>
>> +0.5
>>
>> I still have yet to see a clear explanation of why short-circuit is
>> necessary


>
>Short-circuit evaluation is never "necessary" in _any_ language - it's
>just very, very useful sometimes. Python's 'and' operator doesn't _have_
>to be a short-circuit operator, but it's far more useful because it is.
>

>> and therefore iif() unreasonable.
>
>Several of the previous examples have already illustrated this:
>
>z = iif(x, x.getPref(), 'Not specified')
z = x -> x.getPref() -> 'Not Specified'

>
>is broken without short-circuiting.

Regards,
Bengt Richter

Bengt Richter

unread,
Feb 11, 2003, 12:40:12 AM2/11/03
to
On Mon, 10 Feb 2003 19:41:54 +0100, holger krekel <py...@devel.trillke.net> wrote:
[...]
>Now if we had
>
> z = x.getPref() except AttributeError: 'Not specified'
>
>that might add something which we didn't have before
>(in an expression).
That's interesting (I saw it elsewhere also by you ;-)
I am wondering how I could bring that into my current candidate[1]...

z = x.getPref() >!< AttributeError -> 'Not specified'

z = x.getPref() >!< AttributeError -> 'Not specified' >!< NameError -> 'No x binding'


[1] The basic ternary syntax is
C -> x -> y

Sorry to quote myself, but the 308 threads have proliferated to where I'm not sure whether
anyone will notice if an idea is not posed for comparison in more than one place ...

The above is a concise ternary based on a larger concept (from lisp via Paul Moore with my twist):

the concept was [C1 -> v1; C2 -> v2; C3 -> v3; True -> vDefault] I.e., evaluate Ci's until
you find one that's true, then evaluate its companion v. My twist is to drop the brackets
and supstitute '><' instead of ';'. Thus
C1 -> v1 >< C2 -> v2 >< C3 -> v3 >< True -> vDefault

with a single condition, you have
C1 -> v1 >< True -> vDefault

and by making the final condition introducer '><' and its condition (True) optional, you get
C1 -> v1 -> vDefault

which expresses the ternary nicely without keywords.

The latest twist to catch exceptions introduces exception types with ">!<" and attaches result
expressions with the same "->" as for ordinary conditions. Thus:

C1 -> v1 >< C2 -> v2 >< C3 -> v3 >< True -> vDefault >!< E1 -> ev1 >!< E2 -> ev2

and you work left to right, skipping ordinary condition->value pairs if an exception happens.
Ok, this is now my latest-and-greatest variant ;-)

Regards,
Bengt Richter

Laura Creighton

unread,
Feb 11, 2003, 12:28:28 AM2/11/03
to
> That's not the question. The question is whether or not some forms are
> more readable with the conditional operator than without it. It's
> fundamentally frustrating when people shoot down legitimate examples of
> the conditional operator with, "Oh, but you could have done it _this_
> way." Well, of _course_ you could have. The question is whether the
> conditional form is useful and readable on its own merits.
>
> When people shoot down the max example (e.g., if x > y: x else: y) with
> "Well, you should have used max(x, y)!" is utterly frustrating. Of
> _course_ it could be written that way. We're not asking whether there's
> another way to do it, we're asking whether that is readable on its own
> merits. Those who are against the PEP on general principle seem to
> never understand this distinction.

That is because for many of us this is _not_ what the debate is about.
We don't see Python as some collection of language features, each of
which is to be evaluated on its own merits. We see it as a whole, and
we see what features are _not_ in the language as part of that whole.
So from our end, the question is not 'is this useful and readable' --
pretty much any concept taken from any language has demonstrated
utility and readability. The question is about 'worth changing the
language for'. If you put a high enough value on 'simplicity' and
'lack of diversity' then you will find no language change measures up.
If you find these qualities irrelevant, you can be in favour of every
languge change which could ever produce the most useful and readable
way to express anything. I don't think that anybody is at these
bounds, but that is where they are.

Laura

James J. Besemer

unread,
Feb 11, 2003, 1:21:15 AM2/11/03
to

Dennis Lee Bieber wrote:
>
> <satanic-counsel> "And" and "Or" are technically isolated to the
> evaluation of a condition, and not to the processing of alternatives
> (if any) selected by the result of the condition. In normal languages

"normal languages" ?

> which offer short-circuiting the result of the condition is strictly a
> Boolean; it is only because of the Python semantics which result in
> returning the actual object which was last evaluated rather than
> True/False which even made the work-around possible.

C/C++ and some others return boolean.

LISP long ago defined AND and OR in a Python-like fashion where the argument
was returned instead of a boolean value. LISP also defined a COND operator
which was much like the present if/elif/else expression proposal kicking around.

> Therefore there is
> no valid precedent for using late-binding/lazy-evaluation of the
> branches selected by a condition.

If I understand what you're saying, LISP established such a precedent, like,
30 years ago.

If you meant to say there is no precedence for evaluating both terms of a
conditional expression operator, I think that MIGHT be closer to the truth.

> <defense> Normally blocked if:/else: sequence do not evaluate the
> non-selected branch. Since an inline if is meant to shorten
>
> if cond:
> v = e1
> else:
> v = e2
>
> into a single
>
> v = <TBD SYNTAX>
>
> it is reasonable to presume that unselected brances will not be
> evaluated.</defense>

That seems reasonable to me.

Neil Hodgson

unread,
Feb 11, 2003, 2:33:53 AM2/11/03
to
Erik Max Francis:

> Someone else, I believe, suggested `iif', but I _really_ can't see how
> that helps.

iif has been around since at least Lotus 123 (IIRC) where it was the
inline if function: iif (cond, trueval, falseval). Commonly used in
spreadsheets and low end databases.

Neil


Bengt Richter

unread,
Feb 11, 2003, 2:34:08 AM2/11/03
to
On Mon, 10 Feb 2003 11:16:54 -0800, David Eppstein <epps...@ics.uci.edu> wrote:

>On 2/10/03 7:36 PM +0100 holger krekel <py...@devel.trillke.net> wrote:
>>> My feeling is that the reason for short circuiting isn't so much because
>>> of side effects (I think we should try to keep expressions as free of
>>> side effects as possible) but because one or both of the two sides may
>>> be undefined and raise an exception if the guard condition is not met.
>>
>> right. in which case learning about and/or (which you have to anyway)
>> often helps. Because of the "y is false" problem in "x and y or z"
>> there are some cases where it doesn't fit. Do we have real code
>> examples for them?
>
>I posted one several hundred messages back:


> cols[i] if i >= 0 else None
>

0<=i<len(cols) -> cols[i] -> None

would be even safer, using cond -> trueExpr -> falseExpr

Regards,
Bengt Richter

Erik Max Francis

unread,
Feb 11, 2003, 3:00:22 AM2/11/03
to
holger krekel wrote:

> James J. Besemer wrote:
>
> > You silly.
>
> This is not a great way to argue. Despite the huge amount of
> discussions we have managed to have a rather friendly discussion.
> Why do you want to change it?

Holger, I'm presuming that English isn't your primary language, so maybe
you don't know this, but "You silly" is an idiom which is quite frankly
very playful and is not at all what I'd call unfriendly (unprofessional,
maybe).

If someone says, "You silly! So and so," they are in a way playfully
disagreeing. The tone may not be right, but I don't think it has quite
the negative connotations that you're perceiving from it.

--
Erik Max Francis / m...@alcyone.com / http://www.alcyone.com/max/
__ San Jose, CA, USA / 37 20 N 121 53 W / &tSftDotIotE

/ \ There I was / There I was / Splitting atoms with my desire
\__/ Lamya
Computer science / http://www.alcyone.com/max/reference/compsci/
A computer science reference.

James J. Besemer

unread,
Feb 11, 2003, 2:28:55 AM2/11/03
to

Aahz wrote:

>>Not true, as I and others have explained at length elsewhere. Readability
>>and maintainability are SERVED by factoring out common sub-expressions from
>>the more verbose forms:
>>
>> if condition1:
>> if condition2
>> targetVar1 = result1
>> else:
>> targetVarl = result2 # hidden BUG!!
>> else:
>> targetVar1 = result3
>
>
> How is what you're saying here an argument against a conditional
> function?

Once again, you pointlessly stoop to emphasize the painfully obvious.
Obviously my example in this case has nothing to do with conditional
evaluation. The more astute readers probably gleaned from the text that I
was in this case working on a different point altogether. Yes, these
particular important benefits apply equally well to your iff() proposal.

> Seems to me that short-circuit is the *only* reason to dislike iif();

I dislike it because it's a functional form for what should be a standard
operator.

I further object to it's pointlessness, as in the absence of conditional it
won't provide a viable alternative to the inferior and/or idiom. I suspect
you like it so much precisely because it essentially defeats the PEP.

> and therefore you need to make your argument on changing the language
> (rather than the library) solely on the short-circuit point. That's a
> lot tougher, I think.

True.

But if he approves the proposal at all, I trust that Guido will see the
wisdom of going ahead and including the short circuit functionality, various
'statistical' and emotional arguments of dubious validity notwithstanding.

After all, short circuit functionality was integral to his original draft PEP
AND to the reference implementation he worked on previously. As some have
acknowledged, it's a slightly 'advanced' feature and perhaps only the wiser
of us understand how it's significant merit outweighs the minor cost.

While I doubt he has the stamina to keep up with all the volume coming down
this fire hose of late (especially given the higher than normal fecal
content), I do believe he sees or hears a representative sampling of the
various arguments. I trust him to give much greater weight to the logical
ones vs. the emotional ones.

[BREAKING NEWS]

Ha! Amazingly, while we were arguing (and, seriously, after writing the
above part of this reply), I see that the PEP author has seen the wisdom of
some of our arguments, and now has revised PEP-308, proposing a form which
many may find agreeable.

http://www.python.org/peps/pep-0308.html

Better yet, and more relevant to your question, the revised PEP includes
mention of something like your iff() and then rejects it because, among other
things,

BDFL opposes *any* solution that does
NOT provide short circuit behavior.

Furthermore, there's an entire section devoted to the motivation for short
circuit. Can you say, "End of discussion?"

I'm sure glad I waited until late tonight to begin to address this
(admittedly harder) issue. And I'm even gladder that I double checked the
PEP before attempting it, especially after such a long day. Best of all, I'm
glad to find that my trust in the right hon. BDFL was not misplaced, though
I'm amazed and astonished how quickly he came through.

Nighty night, all, and sleep tight.

Erik Max Francis

unread,
Feb 11, 2003, 3:03:19 AM2/11/03
to
Bengt Richter wrote:

> z = x.getPref() >!< AttributeError -> 'Not specified'
>
> z = x.getPref() >!< AttributeError -> 'Not specified' >!<
> NameError -> 'No x binding'

No offense, but your proposal is frightening more and more as you
expound on it :-).

Erik Max Francis

unread,
Feb 11, 2003, 3:05:18 AM2/11/03
to
Aahz wrote:

> Because the extra punctuation calls out more clearly, IMO. Also, I
> like
> the "||" meaning "or".

But || only means "or" in this sense if you've experienced it from the
C-like languages. The bitwise or operator from Python is |; seeing two
in a row doesn't make one automatically think, "Oh, that must be
_logical_ or! So that question mark is a test! Oh, this is a little
baby if-then-else!"

--
Erik Max Francis / m...@alcyone.com / http://www.alcyone.com/max/
__ San Jose, CA, USA / 37 20 N 121 53 W / &tSftDotIotE

Erik Max Francis

unread,
Feb 11, 2003, 3:06:39 AM2/11/03
to
Alexander Schmolck wrote:

> Frequency * expressivness comes close to measure the usefulness of a
> construct. So for something that adds near 0 expressiveness, the
> frequency
> argument is extremely convincing.

So now to use these frequency statistics (which are contentious by about
an order of magnitude), all we have to do is come up with a metric for
expressiveness that everyone will agree on to legitimize these
statistics. Hmm, right.

--
Erik Max Francis / m...@alcyone.com / http://www.alcyone.com/max/
__ San Jose, CA, USA / 37 20 N 121 53 W / &tSftDotIotE

Erik Max Francis

unread,
Feb 11, 2003, 3:15:33 AM2/11/03
to
Paul Rubin wrote:

> Andrew, I keep wondering why you post these statistics. I gather the
> low frequency of conditional expressions (CE's) in code that you
> examine is supposed to be some kind of evidence that they're not

> useful all that frequently. However, empirically, whether they're
> useful frequently or not, they're useful often enough that people keep
> asking about them and we get these endless threads.

_And_ the broken alternatives get used in the standard library in
_Python_ code!

This isn't an abstract matter of "Gee, what if," the deficient
alternatives _are_ being used, even by seasoned Python programmers.
And, as we've all seen from Andrew Koenig's example, cause bugs. In the
standard library.

Erik Max Francis

unread,
Feb 11, 2003, 3:51:42 AM2/11/03
to
Neil Hodgson wrote:

> iif has been around since at least Lotus 123 (IIRC) where it was
> the
> inline if function: iif (cond, trueval, falseval). Commonly used in
> spreadsheets and low end databases.

Oh, okay. I wasn't aware it actually came from somewhere.

--
Erik Max Francis / m...@alcyone.com / http://www.alcyone.com/max/
__ San Jose, CA, USA / 37 20 N 121 53 W / &tSftDotIotE

/ \ I always entertain great hopes.
\__/ Robert Frost
REALpolitik / http://www.realpolitik.com/
Get your own customized newsfeed online in realtime ... for free!

Andrew Koenig

unread,
Feb 11, 2003, 10:02:54 AM2/11/03
to
Dennis> <satanic-counsel> "And" and "Or" are technically
Dennis> isolated to the evaluation of a condition, and not to the
Dennis> processing of alternatives (if any) selected by the result of
Dennis> the condition. In normal languages which offer
Dennis> short-circuiting the result of the condition is strictly a
Dennis> Boolean; it is only because of the Python semantics which
Dennis> result in returning the actual object which was last evaluated
Dennis> rather than True/False which even made the work-around
Dennis> possible. Therefore there is no valid precedent for using
Dennis> late-binding/lazy-evaluation of the branches selected by a
Dennis> condition. </satanic-counsel>

...

Dennis> Okay, can someone help me off this picket fence? <G>

Python is not the only language in which the result of an "and"
or "or" is one of its operands rather than a boolean. Icon (the
work of Ralph Griswold and friends at the University of Arizona)
has similar behavior. In fact, in Icon, every expression is a
generator that can yield a sequence of results. The convention
in Icon is that an empty sequence indicates failure.

The following Icon operations are relevant to this discussion:

x1 & x2 fails if x1 fails; otherwise yields x2

x1 | x2 generator concatenation (which has the
effect of logical "or" if a null sequence
indicates false)

if expr1 then expr2 else expr3
if expr1 is empty, the result is expr3;
otherwise the result is expr2

I'm not sure which way this example argues, but think it's worth
pointing out in any case.

--
Andrew Koenig, a...@research.att.com, http://www.research.att.com/info/ark

Aahz

unread,
Feb 11, 2003, 10:18:15 AM2/11/03
to
In article <3E48AEBE...@alcyone.com>,

Erik Max Francis <m...@alcyone.com> wrote:
>Aahz wrote:
>>
>> Because the extra punctuation calls out more clearly, IMO. Also, I
>> like the "||" meaning "or".
>
>But || only means "or" in this sense if you've experienced it from the
>C-like languages. The bitwise or operator from Python is |; seeing two
>in a row doesn't make one automatically think, "Oh, that must be
>_logical_ or! So that question mark is a test! Oh, this is a little
>baby if-then-else!"

No, of course not. But at least the two meanings are *related*. I
don't consider the ability to understand conditional expressions without
reading the documentation a high priority.

Alexander Schmolck

unread,
Feb 11, 2003, 10:17:41 AM2/11/03
to
Erik Max Francis <m...@alcyone.com> writes:

> Alexander Schmolck wrote:
>
> > Frequency * expressivness comes close to measure the usefulness of a
> > construct. So for something that adds near 0 expressiveness, the
> > frequency
> > argument is extremely convincing.
>
> So now to use these frequency statistics (which are contentious by about
> an order of magnitude), all we have to do is come up with a metric for

Even with an order of magnitude uncertainty (and I'd think one could do
better), the frequency doesn't look to impressive, does it?

> expressiveness that everyone will agree on to legitimize these
> statistics. Hmm, right.

Even without bothering to come up with some formal and quantifiable criterion
of expressiveness, couldn't we just reach the consensus that something that
can be trivially and compactly rewritten with existing language constructs
isn't all that expressive?

So what's wrong with arguing against polluting and complicating the language
with a construct that seems to be both used infrequently and be easily
replaceable in those rare instances were it is used?

Do you have a better criterion to from the basis for debate (maybe one with a
more easily defined and empirically investigated metric)?

(BTW, although I don't think its immediately relevant here, there *are* formal
definitions of expressivness:
http://citeseer.nj.nec.com/felleisen90expressive.html)

alex

Anders Hammarquist

unread,
Feb 11, 2003, 10:19:48 AM2/11/03
to
In article <3E4850DB...@alcyone.com>,

Erik Max Francis <m...@alcyone.com> wrote:
>Indeed. There are _always_ alternatives, everybody knows that. The
>issue is not whether or not there is an expression that fundamentally
>cannot be written without the conditional operator, because everybody on
>both sides of the debate knows very well that there is no such thing.

Of course, the conditional is essentially just an abbreviated
if-statement with assignment. I doubt anyone is arguing against
it purely based on the fact that it implements functionality that
is already present. If that was a problem, why do we have
file.readlines() when you could just as well do file.read().split()?

>That's not the question. The question is whether or not some forms are
>more readable with the conditional operator than without it.

Exactly, and if so, whether those cases are frequent and ugly
enough that it warrants new syntax (that will undoubtedly be
abused for purposes where it will make code less readable).
Let's not forget that one of the strengths of python is that
it is easy to read and understand other peoples code, and I
believe at least part of the reason for that is that there
are few constructs in python that encourage abuse. (Cue
someone to reply with a list of two dozen abused constructs.)

> It's
>fundamentally frustrating when people shoot down legitimate examples of
>the conditional operator with, "Oh, but you could have done it _this_
>way." Well, of _course_ you could have. The question is whether the
>conditional form is useful and readable on its own merits.

No, it's not whether it's useful or not on it's own merits alone.
If it were, you could easily argue that every possible construct
under the sun has a use, and therefore python should support them
all. Even perl's implicit variable assignment has some use (as
people do use it), but you're not arguing that something like that
should be added to python are you?

>When people shoot down the max example (e.g., if x > y: x else: y) with
>"Well, you should have used max(x, y)!" is utterly frustrating.

No, this is exactly the point. There's no need for the conditional
in this case because we have max() and that is more readable.

/Anders

--
-- Of course I'm crazy, but that doesn't mean I'm wrong.
Anders Hammarquist | i...@cd.chalmers.se
Physics student, Chalmers University of Technology, | Hem: +46 31 88 48 50
G|teborg, Sweden. RADIO: SM6XMM and N2JGL | Mob: +46 707 27 86 87

Andrew Dalke

unread,
Feb 11, 2003, 3:08:21 PM2/11/03
to
Paul Rubin:
> I thus have to ask: if CE's are so rare, then why does the subject
> matter to you? You won't be required to use them in your own code if
> they're added. And according to your own statistics, you'll very
> seldom have to deal with them in other people's code either.
>
> So I'm sorry, but it really sounds like you're trying to impose your
> stylistic preferences on other people without any practical
> justification. The other CE opponents' posts don't give that
> impression nearly as much.

I generated two sets of statistics:
1) use of if/else statements vs. if/else expression vs. short-circuiting
if/else expression
2) likelihood of misuse of the if/else expression, given more appropriate
Python idioms

The later numbers suggest that whe I do "deal with them in other people's
code" then there is somewhere between a 25 to 50% that it will be be
used in place of more appropriate Python code. This is based on
observing the misuse of ?: in existing C++ code, as in the following
(translated into Python)

n = obj.count() if obj is not None else 0
.... skip a few lines
print obj.name

(Were this written as an if/else statement, the needless code would more
likely have been cleaned up, I think, because the decision point stands
out more.)

I also observed places where the ?: idiom in C does not naturally
fit a if/else expression in Python, because Python is a different language
than C, as in the following (assume the precondition that 0 <= i <= 15)

if i < 10:
hex_c = chr(48 + i)
else:
hex_c = chr(55 + i)

which in an PEP 308 world will likely be written as

hex_c = chr(48 + i if i < 10 else 55 + i)

I find this to be less readable than the first case, and even less
readable than the more Pythonic (IMHO)

hex_c = "0123456789ABCDEF"[i]

And I and others pointed out places where an if/else expression could
be used, but shouldn't because the code was less readable. In that
case, I assigned a somewhat low probability (I think 25%) that the
less readable option would be taken.

Were there low chance of misuse, I would not be too concerned.
However, it is this high likelihood of misuse which causes me to be
against this syntax, and to keep posting these statistics.

Andrew
da...@dalkescientific.com


Andrew Dalke

unread,
Feb 11, 2003, 3:34:37 PM2/11/03
to
James J. Besemer:

> Can you enumerate those negative consequences and quantify their cost some
how?

Did you not see all my posts on just this subject?

Andrew Koenig analyzed his C codebase for use of ?:. He described
if the use of ?: was appropriate or not. I then translated the use to
Python
code and pointed out that in some cases there was a more readable
alternative. (And no, [false, true][bool(exp)] is not considered readable
in my book).

I analyzed a C++ code base and noticed the high number of misuses of
the ?: operator in it. I also noted that many of those cases disappear in
Python, partially because Python has the min/max function (many of the
cases were just to get the min/max of two values).

Someone else (forgot who - my apologies!) did a very nice analysis of
his Python code looking for where the if/else expression could be used,
vs. where it should be used, and noted that those two were not the same.
(Eg, the PEP 308 case was less readable for some cases involving
long lines)

Given these numbers, I could estimate the frequency of PEP 308
use were it put into place.

I then assigned a probability that someone would use an if/else expression
rather than use a more appropriate Python idiom (eg, from lack of
experience with Python idioms like "x = y or default") or because of
a desire to fit things into a single line because it's "terse" rather than
being readable. These numbers were made up, but I think not entirely
unreasonable. These were used to determine the likelihood of proper
use vs. improper use.

Combining the different analysis, I then determined that the ballpark
estimates of use are:

- The if/else expression could be used about once every 400 lines
- The if/else expression will be used about once every 1,000 lines
- The if/else expression with short-circuiting is needed only about
once every 5,000 lines (given other Python idioms)

And the rates of misuse range between 1 misuse for every 1
appropriate use, and 1 misuse for every 3 appropriate uses.

Andrew
da...@dalkescientific.com


Andrew Dalke

unread,
Feb 11, 2003, 3:37:22 PM2/11/03
to
Erik Max Francis
> Andrew Dalke wrote:
> > once every 5,000 lines or so) while an iff()-like builtin function
>
> I'm still puzzled over the choice of `iff' for this idea. In maths, it
> means "if and only if," which is totally the wrong meaning for an "if
> this, otherwise that" function.
>
> Someone else, I believe, suggested `iif', but I _really_ can't see how
> that helps.

Well, I have a math degree, and I saw that 'iif' as 'iff'.

I've since decided to call it an 'ifelse()' builtin so that there
wouldn't be this possibility of confusion.

Andrew
da...@dalkescientific.com


Andrew Dalke

unread,
Feb 11, 2003, 3:51:48 PM2/11/03
to
Erik Max Francis
> You [Andrew] keep invoking the frequency argument. I don't find it
convincing.
> How often are Booleans used? metaclasses? generators? list
> comprehensions? There are plenty of features in Python that _are
> already present_ that are used very rarely. But when they are used,
> they do their job with flying colors.

Alexander Schmolck and others (including Andrew Koenig, who I think was
the first to mention it) have said

Frequency * expressiveness

That is one metric. Howeve, I've also been trying to estimate the
likelihood
of misuse of the if/else expression. I think it's fair to estimate that in
the
code I'll be looking at I should expect to see about a 20% or higher misuse
rate.

> The question is whether or not _when it's used_ it serves its purpose.
> You may think that it is never useful, but clearly others don't. Either
> way, the frequency argument doesn't get either side anywhere.

On the contrary, I have pointed out that there are times when it's
a nice solution to a problem. My problem with many of the arguments
posted here is they only show good use-cases for the if/else expression
and exclude mentioning that people will use it incorrectly and that
the increase in (readability, maintainability, etc.) needs to be balanced
by the decrease in the metric given the misuse.

Booleans are very unlikely to be misused. Metaclasses are
very likely to be used. List comprehensions may be misused, but
have not been that misused to date, though list comprehensions
*with* if/else expressions seem prone to misuse where each
alone is appropriate.

> A conditional operator or form should be short-circuiting, because it
> simply doesn't make sense to go through the trouble of adding one that
> doesn't. Everyone knows that a non-short-circuiting conditional
> function is utterly _trivial_. Why bother adding it if it doesn't short
> circuit, no matter how rare short circuiting is?

Adding a standard 'bool' class with instances named True and
False make it easier for code to interoperate because no
additional translation is needed to interface between the boolean
type used in one package and the boolean type used in another
package.

Similarly, were an 'ifelse' function to be added, it would be
a common name and hence people would use it who would
otherwise not create a project-specific ifelse function on
grounds that it creates a project-specific idiom.

Andrew
da...@dalkescientific.com


Gareth McCaughan

unread,
Feb 11, 2003, 6:35:17 PM2/11/03
to
Aahz wrote:

> You're missing the point. How frequently does this occur such that
> getting all our knickers in a twist is worth it? So far, most of the
> examples pushing a conditional expression have *NOT* required
> short-circut behavior. For the cases where side-effects restrict the
> use of a conditional expression, I think perhaps requiring the use of an
> if statement is the most appropriate way to handle it.

What's the actual *disadvantage* of short-circuiting? Is it only that
if you have to short-circuit then you can't just write a new builtin
and be done with it?

It seems to me that there is *no* advantage to a builtin function
over a new syntax (provided the syntax is chosen well), other than
the implementation effort.

The arguments against (any given version of) the proposal are
1 It enlarges the language and therefore makes it harder to learn.
2 It can be abused to produce horrible code.
3 It's ugly.
4 It's confusing even when not abused.
The arguments for it are
5 It reduces code duplication.
6 It leads to more concise code.
7 If we don't have it, people will use horrible surrogates.

I claim that arguments 1..4 apply just as much to a new builtin
as they do to a new syntax. For concreteness, let's compare
"ifelse(C,x,y)" to "if C: x else: y".

#1: ease of learning.

Learning about a new function takes time, just as learning about
a new bit of syntax does. Does anyone have any evidence that
"ifelse(C,x,y)" would be easier to master than "if C: x else: y"?
I certainly haven't seen any. For what it's worth, my baseless
guess is that beginners are more likely to say "huh?" to the
function than to the if-expression. (I've spent quite a lot of
time teaching programming to 12-15-year-olds using Python, which
may or may not be reason to trust my intuition on this.)

Like it or not, Python consists of the core syntax *plus*
the builtin types and their semantics *plus* the standard
library. Adding a new builtin function makes Python more
complicated just as much as adding a new bit of syntax does.
And, at least for the "if C: x else: y" spelling of the
conditional expression, the new syntax can be explained as
quickly as "if both arms of an if are expressions, you can
write it on a single line and use the whole thing as an expression".

#2: possibility of abuse.

Well, of course, *anything* can be abused; we all know that.
The question is: given any particular level of malignity or
thoughtlessness, how horrible is the resulting abuse likely
to be? :-)

Well, here are a couple of mild-ish abuses in both idioms.
I don't see any reason to prefer the first set to the second.

if ifelse(x<y, x>1, y<1):
stuff
t = ifelse(x<y, ifelse(y<z, z, y), x)
ifelse(x<y, (x,y), (y,x))

if (if x<y: x>1 else: y<1):
stuff
t = if x<y: (if y<z: z else: y) else: x
if x<y: (x,y) else: (y,x)

<unkind>I can see one way in which a builtin function might
lead to less abuse than a new expression: the builtin function
is uglier and less useful, so it will be used less, so it will
be abused less. I don't think that's a strong argument in its
favour.</unkind>

#3: ugliness.

Very subjective. All I can say is: I think the functional form
is ugly. I don't think functions of this kind fit well in Python.
I can't prove any of that, of course.

#4: confusing even in simple cases?

It seems to me that the "ifelse" function is worse than the
if: else: construct in this respect, because the difference
between the when-true clause and the when-false clause is
purely positional. From the million articles already posted
in this thread, I think it's clear that a general problem
with the punctuation-based solutions is that it's often
too easy to get the two consequents switched by mistake,
and an "ifelse" function will make that worse.

I also happen to find all the names proposed for the function
so far confusing; but then, names for functions with many
arguments are almost always insufficiently helpful. Hmm,
that suggests a way to make ifelse(,,) easier to get right:
keyword arguments. if(C, true=x, false=y). Bletch. :-)

*

In summary: all the arguments against new syntax apply
just as well to a new builtin, and a new builtin would be
useful in a strict subset of the cases where new syntax
could be[1]. Remind me what *advantages* a new builtin
is supposed to have over new syntax, again?

[1] And not, so far as I can see, a subset where
inappropriate use is any less likely.

--
Gareth McCaughan Gareth.M...@pobox.com
.sig under construc

Erik Max Francis

unread,
Feb 11, 2003, 8:21:57 PM2/11/03
to
Alexander Schmolck wrote:

> Even with an order of magnitude uncertainty (and I'd think one could
> do
> better), the frequency doesn't look to impressive, does it?

Did you even read what I've said? The frequency by itself means
_nothing_. How often are generators used? list comprehensions?
metaclasses?

No one ever said that conditional operators (in any language) were so
ubiquitous that Python _had_ to have them. Frequency arguments defeat
strawmen.

> Even without bothering to come up with some formal and quantifiable
> criterion
> of expressiveness, couldn't we just reach the consensus that something
> that
> can be trivially and compactly rewritten with existing language
> constructs
> isn't all that expressive?

Right, with idioms that are short, unreadable, and wrong.

--
Erik Max Francis / m...@alcyone.com / http://www.alcyone.com/max/
__ San Jose, CA, USA / 37 20 N 121 53 W / &tSftDotIotE

/ \ Being in love for real / It ain't like a movie screen
\__/ India Arie
Bosskey.net: Aliens vs. Predator 2 / http://www.bosskey.net/avp2/
A personal guide to Aliens vs. Predator 2.

Andrew Dalke

unread,
Feb 11, 2003, 8:31:46 PM2/11/03
to
Gareth McCaughan:

> The arguments against (any given version of) the proposal are
> 1 It enlarges the language and therefore makes it harder to learn.
..

> #1: ease of learning.
>
> Learning about a new function takes time, just as learning about
> a new bit of syntax does. Does anyone have any evidence that
> "ifelse(C,x,y)" would be easier to master than "if C: x else: y"?

Evidence? No. However, languages are designed (nearly always)
with the ability to get new functions without changing the syntax
of the language. On the other hand, few languages are designed
so the syntax can be changed.

As such, as new function is part of the existing language,
while new syntax is part of a new language which just happens
to be close to the old one.

> Adding a new builtin function makes Python more
> complicated just as much as adding a new bit of syntax does.

No, it does not. For example, if you want to find out
what the "ifelse" function does, you can do

>>> help(ifelse)

or use the corresponding help facilities of your IDE
of choice.

In general, you cannot do so with syntax. "help([)"
does not work.

> #2: possibility of abuse.
>
> Well, of course, *anything* can be abused; we all know that.
> The question is: given any particular level of malignity or
> thoughtlessness, how horrible is the resulting abuse likely
> to be? :-)

According to my estimates, based on the analysis of existing
C/C++ code and of existing Python code, I believe the
misuse rate will be about 1 misuse for every 3 proper uses.

(Actually, I think that's the low end and the misuse rate
will be higher, but I'm willing to live with it for the point
of dicussion.)

Andrew
da...@dalkescientific.com


Delaney, Timothy C (Timothy)

unread,
Feb 11, 2003, 8:14:41 PM2/11/03
to
> From: Gareth McCaughan [mailto:Gareth.M...@pobox.com]

>
> What's the actual *disadvantage* of short-circuiting? Is it only that
> if you have to short-circuit then you can't just write a new builtin
> and be done with it?

Control flow is not explicit. As I stated on another thread (damn - I was trying not to get involved in this too much ;) I have yet to read a ternary which *relies* on short-circuiting without needing to think hard about it.

Control flow should be explicit. Anything which participates in a short-circuiting expression should behave identically if the short-circuiting were not present. Short-circuiting should be an optimisation only.

i.e. You shouldn't have side-effects in a short-circuiting expression.

Tim Delaney

Paul Rubin

unread,
Feb 11, 2003, 11:33:11 PM2/11/03
to
Dennis Lee Bieber <wlf...@ix.netcom.com> writes:
> From *VB & VBA in a Nutshell*
>
> IIF(expr, truepart, falsepart)
>
> notes indicate that both xxxpart ARE evaluated regardless of expr

As much as I don't like the reasoning that Python must do the opposite
of whatever C does, there's some grounds for doing the opposite of what
VB and VBA do. Ugh!

Anna

unread,
Feb 11, 2003, 11:36:47 PM2/11/03
to
On Mon, 10 Feb 2003 15:52:24 +0000, Raymond Hettinger wrote:

> I suggest:
>
> cond ?? val1 || val2
>
> * Having two characters at each step helps visually segregate the
> components.
> * The ?? and || strongly suggest testing and alternation. * Doesn't
> overload or confuse with existing operators. * No new keywords. *
> In-order presentation.
> * Short and easy to read.
>
>
> Using Martin Maney's live code examples, here's what it looks like:
> i = j>=0 ?? j || n
> sy = d0.year - (d0.month<7 ?? 1 || 0) add2url = '?' +
> (params.has_key('add2url') ?? params['add2url'] ||
> '')
> tail = (len(events)>1 ?? ' ' || '<br>') + tail

Y'know, when I finished my first Python script, I sent it to my tutor and
asked: "So what's the Secret Master Pythonista way of doing this?" His
response is etched in my mind: "Python isn't about taking 10 lines of
perfectly clear code and collapsing it down into 1 line of obscure code.
That's Perl..."

And that keeps coming to mind as I'm reading all these "ternary operator"
syntax proposals... Most of them, to my newbie eyes, are simply confusing,
and seem to fly in the face of what I keep hearing Python is about. Maybe
I'm just being dense, but I haven't seen any that are terribly clear; the
worst ones make me want to pull out a pencil and paper and sit down with
the docs in front of me to try and figure out what the heck it's supposed
to *do*...

...which seems really odd for code that's supposed to be easily readable.

Just my $.03 worth.
Anna
--
Whatever it is, I'm against it. -Groucho Marx

Aahz

unread,
Feb 12, 2003, 12:25:19 AM2/12/03
to
In article <pan.2003.02.12....@mn.rr.com>,

Anna <rev...@mn.rr.com> wrote:
>
>Y'know, when I finished my first Python script, I sent it to my tutor and
>asked: "So what's the Secret Master Pythonista way of doing this?" His
>response is etched in my mind: "Python isn't about taking 10 lines of
>perfectly clear code and collapsing it down into 1 line of obscure code.
>That's Perl..."
>
>And that keeps coming to mind as I'm reading all these "ternary operator"
>syntax proposals... Most of them, to my newbie eyes, are simply confusing,
>and seem to fly in the face of what I keep hearing Python is about. Maybe
>I'm just being dense, but I haven't seen any that are terribly clear; the
>worst ones make me want to pull out a pencil and paper and sit down with
>the docs in front of me to try and figure out what the heck it's supposed
>to *do*...
>
>...which seems really odd for code that's supposed to be easily readable.

That, in a nutshell, is what this argument is about. The problem is,
there's a natural tension for expert programmers to want to express
themselves easily and tersely, and there's a natural tendency for
programming language designers to cater to that. In a very real sense,
it's no different from the desire of someone with an encylopedic
knowledge of a language desiring to find the single perfect word to
express meaning rather than relying on a more complex phrasing. Python
has so far done an excellent job of maintaining a balance between all the
different tensions; those who are unutterably opposed to any form of
conditional expression fall completely into your camp.

Paul Rubin

unread,
Feb 12, 2003, 1:11:52 AM2/12/03
to
aa...@pythoncraft.com (Aahz) writes:
> >Y'know, when I finished my first Python script, I sent it to my tutor and
> >asked: "So what's the Secret Master Pythonista way of doing this?" His
> >response is etched in my mind: "Python isn't about taking 10 lines of
> >perfectly clear code and collapsing it down into 1 line of obscure code.
> >That's Perl..."
>
> That, in a nutshell, is what this argument is about. The problem
> is, there's a natural tension for expert programmers to want to
> express themselves easily and tersely, ... Python has so far done

> an excellent job of maintaining a balance between all the different
> tensions; those who are unutterably opposed to any form of
> conditional expression fall completely into your camp.

I don't see it that way. I see a camp that wants a clear, definite,
explicit way to express a conditional expression, and a camp that
prefers "Secret Master Pythonista" bizarre idioms like "x and y or z,
with rework required if it turns out that y can be None or 0 or the
empty list". From my view, conditional expressions are in the
simplicity camp and "x and y or z" is from the Secret Master Pythonista
camp.

Michael Hudson

unread,
Feb 12, 2003, 8:53:51 AM2/12/03
to
Paul Rubin <http://phr...@NOSPAM.invalid> writes:

> I don't see it that way. I see a camp that wants a clear, definite,
> explicit way to express a conditional expression, and a camp that
> prefers "Secret Master Pythonista" bizarre idioms like "x and y or z,
> with rework required if it turns out that y can be None or 0 or the
> empty list".

Well, then you have to explain me.

I don't think the addition of any of the proposed conditional
expressions to Python would be a good thing.

I *do not* prefer the "_ and _ or _" abomin^Widiom.

I think the Peters-ly signoff to my last post on this subject will be
appended to any more I make:

learn-to-love-the-return-key-ly y'rs,
M.

--
I think perhaps we should have electoral collages and construct
our representatives entirely of little bits of cloth and papier
mache. -- Owen Dunn, ucam.chat, from his review of the year

It is loading more messages.
0 new messages