"for" with "else"?

D

David Eppstein

Stephen Horne said:
I still think that exception-based approaches are far from painful for
this kind of stuff. However, with your example from binhex.py...

for c in data:
if not c.isspace() and (c<' ' or ord(c) > 0x7f):
break
else:
finfo.Type = 'TEXT' ....
Actually, there is a very clean and expressive approach that I'd use
if I had access to my own library stuff...

if mylib.exists (lambda c : c in string.printable, data) :
finfo.Type = 'TEXT'

with, in 'mylib'...

def exists (pred, seq) :
for i in seq :
if pred(i) : return True
return False

...which is, of course, cheating as that return is just as
unstructured as a break - but I don't mind cheating too much when it
is localised in a trivial library function.

Haven't you inverted the logic here?
You want a universal quantifier, not an existential one.
 
S

Stephen Horne

Haven't you inverted the logic here?
You want a universal quantifier, not an existential one.

Yes, absolutely correct.

I did some hacking around with different ways of representing this.
The condition got inverted a few times. The final version was derived
from something like this...

if not mylib.exists (lambda c : c not in string.printable, data) :
finfo.Type = 'TEXT'

And I forgot to switch the quantifier when I inverted the logic for
some bizarre reason. I guess that's what happens when you spend too
much time obsessing over a piece of code - the longer you spend
fussing over it the greater the odds of making a stupid mistake, and
the less likely you are to spot it :-(

So yes, the debugged version is...

if mylib.always (lambda c : c in string.printable, data) :
finfo.Type = 'TEXT'

with...

def always (pred, seq) :
for i in seq :
if not pred(i) : return False
return True


While these 'every' and 'always' functions are trivial, they are also
pretty useful and obviously based on the common discrete maths
notation so not unique to me.

Could some simple functions like this have a place in the library
somewhere?
 
A

Alex Martelli

Stephen Horne wrote:
...
def always (pred, seq) :
for i in seq :
if not pred(i) : return False
return True

While these 'every' and 'always' functions are trivial, they are also
pretty useful and obviously based on the common discrete maths
notation so not unique to me.

Could some simple functions like this have a place in the library
somewhere?

They might, *EXCEPT* that "passing a callable" is out of fashion, and
out of favour, in the BDFL's current opinion -- and for good reasons,
too, although they MIGHT change in the future. The BDFL is on record
as regretting ever having accepted lambda into the language, and map,
filter and reduce into the languages' builtins; 3.0 (maybe in 2-3 years)
will be mostly about *simplification*, i.e. *removal* of some of the
"more than one way" things that have accreted over the years, and in
that release lambda and the 'functional'-ish built-ins are quite likely
to go (the latter might get moved to some backwards-compat module); such
new language features as list comprehensions have among their major pluses
the ability to NOT "pass callables" but rather write code in-line.

So I strongly doubt that any new construct *ENCOURAGING* people to
write "if always(lambda x: x>23, myseq):" and the like stands any
substantial chance of getting into the language and built-ins. I
could be wrong, of course; channeling Guido is Tim Peters' job, not
mine. But if you could figure out a GOOD Pythonic way to pass an
anonymous codeblock into a function, as e.g. Ruby and Smalltalk do
so naturally -- particularly a good SYNTAX, that's the hardest part --
THEN you might stand a good chance of "revolutionizing" Python, at
least at 3.0 time. The ability to code predicates inline would be
key, here. Neither:
if always(lambda x: x>23, myseq):
...
nor:
def gt23(x): return x>23
if always(gt23, myseq):
...
are currently considered GOOD. What might be? I dunno. Ruby's
concepts (that the block, if present, always goes AFTER the function;
only one block can be there, at most; ...) might be acceptable limits
if they helped a good syntax; lambda's current limit (no statements,
just an expression -- and all the distortions THAT encourages) is
not acceptable.

E.g., suppose (and I doubt it IS so in reality:) that making 'def'
do double duty was deemed acceptable; 'def' would denote a statement
when used like today, but it might also be an _expression_ instead,
if and only if used as the last actual-argument to a function, a la:

if always(myseq, def isgood(x): return x>23):
...

or:

if always(myseq, def memoized_predicate(x):
try: return _memo[x]
except KeyError:
_memo[x] = lots_of_computations(x)
return _memo[x]
):
...

THEN, _IF_ the BDFL liked this specific syntax (and, to repeat,
I strongly doubt he would!!!), you MIGHT well get your 'always',
'exists', etc etc -- and many other neat ideas currently held
in limbo because of the "passing a callable" issue might also
get "unblocked". Among the problems is, there is no precedent
for an _expression_ being whitespace/indentation sensitive, yet
something like that would be indispensable for any such idea...


Alex
 
S

Stephen Horne

They might, *EXCEPT* that "passing a callable" is out of fashion, and
out of favour, in the BDFL's current opinion -- and for good reasons,
too, although they MIGHT change in the future.

I agree mostly. At present, first-class functions are very powerful
tools, but they certainly have some drawbacks.

The trouble, as you said, is the syntax. At present, the most natural
syntax happens in list comprehensions - where the language grammar
isolates the 'code block'. It's hard to think of a good syntax which
(1) doesn't recreate lambda to explicitly mark out the 'code block',
and (2) can exist within Pythons existing dynamic model.

:-(
 

Ask a Question

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

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

Ask a Question

Members online

Forum statistics

Threads
473,774
Messages
2,569,596
Members
45,143
Latest member
SterlingLa
Top