'for every' and 'for any'

Quinn Dunkan quinn at schilling.ugcs.caltech.edu
Tue May 28 12:01:40 EDT 2002


On Tue, 28 May 2002 02:33:11 -0400, Oren Tirosh <oren-py-l at hishome.net> wrote:
>On Sun, May 26, 2002 at 09:17:47AM -0500, jepler at unpythonic.net wrote:
>> On Sun, May 26, 2002 at 01:59:44PM +0300, Oren Tirosh wrote:
>> > Here's an idea for a possible language enhancement.  I'd like to hear your
>> > comments about it.  It's inspired by list comprehensions and I think the
>> > examples are pretty self-explanatory:
>> > 
>> > if not isinstance(x, str) for any x in args:
>> >   raise TypeError, "arguments must be of type str"
...
>Anyway, the common task of checking if all or any of the items of a list
>match a certain predicate is implemented in a large variety of ways. Just
>in the replies to my message I got implementations that use break
>statements, exceptions to break of of the loop, flags, checking for empty 
>lists, comparing list length to the original list and reduce with lambdas.
>I've also seen a lot of code that uses the return statement as a kind of 
>break to achieve this effect.

The standard lisp functions EVERY and SOME are easily written in python:

def every(f, seq):
    for e in seq:
        if not f(e):
            return 0
    else:
        return 1
def some(f, seq):
    for e in seq:
        if f(e):
            return 1
    else:
        return 0

Then the above becomes:

if not every(is_string, args):
    raise TypeError('why is that "brick" so "bleck"?')

where:

def is_string(o):
    'checking for stringp is more complicated if you include unicode'
    # if you want backward compatibility, it's even more complicated
    return some(lambda t: isinstance(o, t), types.StringTypes)

>The fact that there is no simple, common idiom to express this operation 
>seems to suggest that this part of the language is not as natural as it
>could be.  Most common ways to express this operation make use control flow 
>statements rather than expressions which makes them more awkward to use. 

The above functions are how I would solve the problem at first glance
(though I'd probably call them "any" and "all" after haskell).  They're not
builtin to python but are standard in many other languages.  Any any case, it
seems quite simple and natural to me (as well as being an expression).

The fact that I don't have them in my util library probably means I don't need
them very often and when I do I find it easier to write three lines of loop.
Probably because the loop is so easy, and if you take the any/all route you
soon find yourself writing curry() and before you know it you're generating
thunks to foil eager evaluation and then you realize you're well down the
slipperly slope and made a big mess of things by writing non-pythonic python.

>An expression is easy to use in an if statement where you get an else 
>clause. Using combinations of break makes it harder to use both the positive 
>and negative case. I often find myself rearranging my code and sometimes 
>inverting tests just to get what I want. That's not what programming is all 
>about. I'd rather concentrate on the task at hand than on how to express it.

Then drop those functions into your personal utility library and use 'em
as often as you want :)



As an aside, I'm sure you know this and your example was just a silly example,
but explicitly checking types is usually bad form in python.



More information about the Python-list mailing list