[Python-ideas] Where-statement (Proposal for function expressions)

Gerald Britton gerald.britton at gmail.com
Thu Jul 16 15:39:01 CEST 2009


> Huh?
> How do you come at this step? IMHO myfunc(bar) is not the same as
> lambda x,y: myfunc(x)(bar(y)).
> It would be the same as (lambda x: myfunc(x))(lambda y: bar(y))

Possibly, I wrote it up in a hurry.  Perhaps this one is clearer:


foo = lambda (x,y): myfunc(bar) where:
     myfunc = getattr(x, 'func')
     bar = str(y)

Should be the same as:

foo = lambda (x,y): getattr(x, 'func')(str(y))

The "where" clause is just syntactic sugar but can make some things
easier to follow.  Even in the toy example above it is tough to
(visually) parse:

    getattr(x, 'func')(str(y))

and some feel that breaking it down bit by bit is easier.  So the
example could be written:

def foo(x,y):
    myfunc = getattr(x, 'func')
    bar = str(y)
    return myfunc(bar)

It really comes down to a matter of taste.  Should the programmer be
forced to define things in execution order (like the def foo, above)
or should there be freedom to define things when you absolutely need
to (the example with the "where" clause)?

Another example:

  area(x) = pi * r ** 2 where:
        import math
        pi = math.pi
        r = circle.get_radius()
        where:
             circle = Circle(object)
             where:
                    class Circle(radius):
                          def __init__(self, radius):
                                self.radius = radius
                          def get_radius(self):
                                return self.radius

I know, it starts to look absurd after a while.  However, I would use
it if available to make long expressions more readable.  For example,
say I have a database class with many functions with descriptive names
that are a bit long.  Let's set it up this way:

class MyDataBase(DB):
     def __init__(self, path):
         self.path = path
     ...
     def get_records_with_key(self, key):
         rec = db.get_by_key(key)
         while rec:
             yield rec
             rec = db.get_next_by_key(key)

Now, in my code I might have a snippet:

    employees = MyDataBase('employees.db')
    ....
    smiths = [record for record in db.get_records_with_key('smith')]

If I has a "where" clause, I'd prefer to write this:

    smiths = [record for record in stuff] where:
                      stuff = db.get_records_with_key('smith')

Of course there are other ways to write this in standard Python, but I
don't think that's the point of this thread.  I think that adding a
"where" clause would make it possible to write deep list
comprehensions and other long expressions without lots of parentheses.
 I suspect that I'm not alone in messing up either the placement or
number of parentheses or both.

Here's another one. Remember that a generator expression sometimes
needs parentheses and sometimes not?  For example:

from itertools import chain
c = chain(i for i in [2,3,5,7,11])   # no parentheses around the generator
d = chain( (i for i in [2,3,5]) , (j for j in [7,11] )  # needs parentheses

It's easy to mess up the extra parentheses (I sure do (and did, above!))

This might be nicer:

d = chain(g1, g2) where:
         g1 = (i for i in [2,3,5])
         g1 = (j for j in [7,11])

Even though there are just as many parentheses, they're broken out and
easier to spot.  Sure, you could define g1 and g2 ahead of time, but
if the "where" clause creates a new namespace like a function def in a
function, then g1 and g2 are just placeholders in the expression and
don't pollute the variable namespace of the calling context.

Anyway, I don't feel strongly either way.  I see the benefits of
"where" clauses and I'd use them if they were available, but I can
certainly do without.



More information about the Python-ideas mailing list