I sing the praises of lambda, my friend and savior!

Clark C. Evans cce at clarkevans.com
Tue Oct 12 18:23:02 CEST 2004


On Mon, Oct 11, 2004 at 07:47:43PM -0700, Jeff Shannon wrote:
| Robert Brewer wrote:
| >xforms = {dejavu.icontains:
| >           lambda x, y: x + " Like '%" + y[1:-1] +"%'",

Robert had 3 examples of a particular lambda, in this case, I'd
consider making a separate function, 'unquote' which seems to 
be what he's doing.  However, the idea of a lookup table having
a great many varieties of thingies is not uncommon; and lambda
is very useful in this case.

| >Conciseness is a continuum. I understand (and agree with) your
| >contention that many lambdas wouldn't suffer from a full function
| >definition. Writing the above with full functions, however, would take
| >us to the other extreme end of the continuum, which is boilerplate for
| >boilerplate's sake.

  Hear Hear!

| Well, all I can say is that I had to sit down and work through some 
| examples to figure out what each of those lambdas would do.

Your problem seems to be with using string concatination (a very 
straight-forward and common method of building strings, I might add)
rather than with lambda, 

 xforms = {  
         dejavu.icontains: 
              lambda x,y: "%s Like '%%%s%%' % (x,y[1:-1]),
         dejavu.ieq: 
              lambda x,y: "%s = %s" % (x,y),
         dejavu.now: lambda: "Now()",
         dejavu.today: lambda: "DateValue(Now())",
         dejavu.year: 
              lambda x: "Year(%s)" % x
         }

| I'm also not sure what the point is of defining a callable that returns 
| a literal string, but I suppose you're just following a protocol 
| established elsewhere.

This is called lazy evaulation, the caller doesn't _know_ that it is
just a string till it evaluates the code block.  It could, just as easily
be, for example, a computation that creates a string.

            lambda: "current time is %s" % time.ctime()

This expression varies depending on when you ask for its value.

| Personally, I'd be likely to solve this particular issue by defining a 
| make_formatter() function:
| 
| def make_formatter(format):
|    def formatter(*args):
|        return format % tuple(args)
|    return formatter
| 
| xforms = {dejavu.icontains: make_formatter("%s Like '%%%s%%'"),
...
|          }
| 
| # [...]
| xforms[dejavu.icontains](x, y[1:-1])

What you've done:
  - completely changed the semantics of his example
  - made the logic not quite so easily understandable; I have to
    now "look" for the definition of make_formatter
  - created a rather 'useless' function and clouded my head 
    with a name for it
  - used alot more vertical space in my code that amounts
    to a few (unnecessary) extra pages to deal with.

Also, your make_formatter is a very simple lambda:

  xforms = { dejavu.icontains: 
                lambda *args: "%s Like '%%%s%%'" % args,

That ain't so hard is it?

| I suppose that the fact that all of these methods just happen to be 
| building strings may be an artifact of the specific example, rather than 
| a general case.  I haven't really needed to use adapters, so I can't 
| really say how often a general transformation along these lines might be 
| applicable...

This string building is quite common in the style of programming
I use as well.  It is a general case for me, and lambda makes my
life much nicer.

On Mon, Oct 11, 2004 at 01:51:00PM -0700, Jeff Shannon wrote:
| But because of Python's line- and indentation-based syntax, doing all of 
| that on a single line is... um... awkward at best, to put it mildly.  

There are lots of things in python that can be single-line, including
at this point the ability to declare and invoke a function.  For
example, I can declare a mapping or sequence using a single-line
format, ["such", "as", "this", "list"] or { "like": "this dict" }.

I like the ability to use my entire 80 column screen for code, when
appropriate.  While the indentation helps readability, it should not
be forced when it is not necessary.   How ugly would python be if it
forced lists to be declared one-line-per-list-item?

| And once you make a lambda multiline, then you lose most of the point of 
| it -- at least, as far as I understand what the point is (having an 
| in-line, anonymous callable).  Once you allow statements and multiple 
| expressions, all you're gaining is anonymity, which seems like a pretty 
| paltry benefit to me.

The primary advantage of lambda is that it defines a function where
you need it, not before.  The ability to use screen realestate better
is a nice advantage, as is not having to 'mint' a name for temporary use.

Instead of arguing against lambda, which is already in the core language
and used by many people, perhaps you could suggest a syntax improvement
that would make lambda more understandable?  Your're advocating taking
away a very nice tool without proposing a resonable replacement.

Best,

Clark

-- 
Clark C. Evans                      Prometheus Research, LLC.
                                    http://www.prometheusresearch.com/
    o                               office: +1.203.777.2550 
  ~/ ,                              mobile: +1.203.444.0557 
 //
((   Prometheus Research: Transforming Data Into Knowledge
 \\  ,
   \/    - Research Exchange Database
   /\    - Survey & Assessment Technologies
   ` \   - Software Tools for Researchers
    ~ *



More information about the Python-list mailing list