Development

NAVIGATION
CATEGORIES
REFERRENCE
LINKS
  • A critic of Guido's blog on Python's lambda

    7 answers - 569 bytes - related search similar search Add To My Delicious Add To My Stumble Upon Add To My Google Mark Add To My Facebook Add To My Digg Add To My Reddit

    Alex Martelli wrote:
    I cannot conceive of one. Wherever within a statement I could write the
    expression
    lambda <args>: body
    I can *ALWAYS* obtain the identical effect by picking an otherwise
    locally unused identifier X, writing the statement
    def X(<args>): body
    and using, as the expression, identifier X instead of the lambda.
    This is true, but with lambda it is easier to read:
    Would be interesting to see how this would look like in Python or some of
    the other languages to which this troll thread was posted :-)
  • No.1 | | 1486 bytes | |

    Frank Buss <fb (AT) frank-buss (DOT) dewrote:

    Alex Martelli wrote:

    I cannot conceive of one. Wherever within a statement I could write the
    expression
    lambda <args>: body
    I can *ALWAYS* obtain the identical effect by picking an otherwise
    locally unused identifier X, writing the statement
    def X(<args>): body
    and using, as the expression, identifier X instead of the lambda.

    This is true, but with lambda it is easier to read:

    Would be interesting to see how this would look like in Python or some of
    the other languages to which this troll thread was posted :-)

    Sorry, but I just don't see what lambda is buying you here. Taking just
    one simple example from the first page you quote, you have:

    (defun blank ()
    "a blank picture"
    (lambda (a b c)
    (declare (ignore a b c))
    '()))

    which in Python would be:

    def blank():
    " a blank picture "
    return lambda a, b, c: []

    while a named-function variant might be:

    def blank():
    def blank_picture(a, b, c): return []
    return blank_picture

    Where's the beef, really? I find the named-function variant somewhat
    more readable than the lambda-based variant, but even if your
    preferences are the opposite, this is really such a tiny difference that
    I can't see why so many bits should gets wasted debating it (perhaps
    it's one of Parkinson's Laws at work).

    Alex
  • No.2 | | 852 bytes | |

    Alex Martelli wrote:

    Sorry, but I just don't see what lambda is buying you here. Taking just
    one simple example from the first page you quote, you have:

    (defun blank ()
    "a blank picture"
    (lambda (a b c)
    (declare (ignore a b c))
    '()))

    You are right, for this example it is not useful. But I assume you need
    something like lambda for closures, e.g. from the page
    :

    (defun black-white (&key function limit)
    (lambda (x y)
    (if ((funcall function x y) limit)
    1.0
    0.0)))

    This function returns a new function, which is parametrized with the
    supplied arguments and can be used later as building blocks for other
    functions and itself wraps input functions. I don't know Python good
    enough, maybe closures are possible with locale named function definitions,
    too.
  • No.3 | | 1310 bytes | |

    Frank Buss <fb (AT) frank-buss (DOT) dewrote:

    Alex Martelli wrote:

    Sorry, but I just don't see what lambda is buying you here. Taking just
    one simple example from the first page you quote, you have:

    (defun blank ()
    "a blank picture"
    (lambda (a b c)
    (declare (ignore a b c))
    '()))

    You are right, for this example it is not useful. But I assume you need
    something like lambda for closures, e.g. from the page

    Wrong and unfounded assumption.

    :

    (defun black-white (&key function limit)
    (lambda (x y)
    (if ((funcall function x y) limit)
    1.0
    0.0)))

    This function returns a new function, which is parametrized with the
    supplied arguments and can be used later as building blocks for other
    functions and itself wraps input functions. I don't know Python good
    enough, maybe closures are possible with locale named function definitions,
    too.

    They sure are, I gave many examples already all over the thread. There
    are *N* semantic advantages for named vs unnamed functions in Python.

    Not sure what the &key means here, but omitting that

    def black_white(function, limit):
    def result(x,y):
    if function(x, y) limit: return 1.0
    else: return 0.0
    return result

    Alex
  • No.4 | | 485 bytes | |

    Alex Martelli wrote:

    Not sure what the &key means here, but omitting that

    def black_white(function, limit):
    def result(x,y):
    if function(x, y) limit: return 1.0
    else: return 0.0
    return result

    &key is something like keyword arguments in Python. And looks like you are
    right again (I've tested it in Pyhton) and my assumption was wrong, so the
    important thing is to support closures, which Python does, even with local
    function definitions.
  • No.5 | | 3675 bytes | |

    There are *N* semantic advantages for named vs unnamed functions in Python.

    I feel that this conversation has glanced off the point. Let me try a
    new approach:

    There is the Pythonic way (whatever that is), and then The Lisp Way. I
    don't know what the former is, but it has something to do with
    indentation, and the (meaningless to me*) phrase "It fits your mind."
    The Lisp way is quite specific: Pure Compositionality. Compositionality
    encompasses and defines all aspects of Lisp, from the parens to
    functional style to fundamental recursion to lambda, and even the
    language itself is classically composed from the bottom up, and
    compositionality enables us to create new complete languages nearly
    trivially.

    How this concept plays into the current conversation is not subtle:
    LAMBDA forms server to directly modify the forms in which they appear.
    SRT is the example that comes to mind for me. If one says: (sort
    #'(lambda (a b) )) [I realize that the #' is optional, I use it here
    for emphasis that there is a function being formed.] the lambda form
    composes, with sort, a new type of sort -- a sort of type <whatever the
    lambda function does>. Thus, the semantics of this form are localized
    to the sort expression, and do not leave it -- they are, indeed,
    conceptually a part of the sort expression, and to require it/them to
    be moved outside and given a name breaks the conceptual
    compositionality -- that is, the compositional locality of the form.

    Similarly, parens and the functional fact that every form returns a
    value provide compositional locality and, perhaps more importantly in
    practice, compositional *mobility* -- so that, pretty much anywhere in
    Lisp where you need an argument, you can pick up a form and drop it in.
    [Macros often break this principle, I'll get to those in a moment.]
    This is something that no other language (except some dead ones, like
    APL) were able to do, and these provide incredible conceptual
    flexibility -- again, I'll use the term "mobility" -- one can, in most
    cases, literally move code as though it were a closed concept to
    anywhere that that concept is needed.

    Macros, as I have said, bear a complex relationship to this concept of
    composition mobility and flexibility. The iteration macro, demonstrated
    elsewhere in this thread, is an excellent example. But macros are more
    subtly related to compositionality, and to the present specific
    question, because, as you yourself said: All you need to do is make up
    a name that isn't usedBut how is one to find a name that isn't used
    if one has macros? [Actually, in Lisp, even if we didn't have lambda we
    could do this by code walking, but I'll leave that aside, because
    Python can't do that, nor can it do macros.]

    I do not hesitate to predict that Python will someday sooner than later
    recognize the value of compositional flexibility and mobility, and that
    it will struggle against parentheses and lambdas, but that in the end
    it will become Lisp again. They all do, or die.

    [*] BA - Biographical Annotation: Yeah, I've programmed all those
    things too for years and years and years. I also have a PhD in
    cognitive psychology from CMU, where I worked on how people learn
    complex skills, and specifically programming. When I say that "fits
    your brain" is meaningless to me, I mean that in a technical sense:
    If it had any meaning, I, of all people, would know what it means;
    meaning that I know that it doesn't mean anything at all.
  • No.6 | | 486 bytes | |

    7 May 2006 13:35:20 -0700, JShrager (AT) gmail (DOT) com declaimed the following
    in comp.lang.python:

    I do not hesitate to predict that Python will someday sooner than later
    recognize the value of compositional flexibility and mobility, and that
    it will struggle against parentheses and lambdas, but that in the end
    it will become Lisp again. They all do, or die.

    In 20 years Python will be indistinguishable from FRTRAN, and
    miles away from LISP <G>
  • No.7 | | 1783 bytes | |

    Frank Buss <fb (AT) frank-buss (DOT) dewrote:

    Alex Martelli wrote:

    Not sure what the &key means here, but omitting that

    def black_white(function, limit):
    def result(x,y):
    if function(x, y) limit: return 1.0
    else: return 0.0
    return result

    &key is something like keyword arguments in Python. And looks like you are

    Ah, thanks.

    right again (I've tested it in Pyhton) and my assumption was wrong, so the
    important thing is to support closures, which Python does, even with local
    function definitions.

    We do appear to entirely agree. In Python <= 2.4, where if is just a
    statement (not an expression), you'd need some trick to get this effect
    with a lambda, e.g.:

    def black_white(function, limit, key=None):
    return lambda x,y: 1.0 * (function(x,y) limit)

    assuming it's important to get a float result -- the operator per se
    returns an int, so you can call float() on it, or multiply it by 1.0,
    etc -- if you had two arbitrary colors, e.g.

    def two_tone(function, limit, key=None, low=0.0, high=1.0):
    return lambda x,y: (low, high)[function(x,y) limit]

    which is a pretty obscure alternative. In Python >= 2.5, an if
    expression has been added, but I'll leave you to judge if it's actually
    an improvement (sigh):

    def two_tone(function, limit, key=None, low=0.0, high=1.0):
    return lambda x,y: high if function(x,y) limit else low

    Personally, I'd rather use the named-function version. Anyway, they're
    all semantically equivalent (sigh), and the key point is that the
    semantics (building and returning functions on the fly) IS there,
    whether the functions are named or unnamed, as we agree.

    Alex

Re: A critic of Guido's blog on Python's lambda


max 4000 letters.
Your nickname that display:
In order to stop the spam: 3 + 3 =
QUESTION ON "Development"

EMSDN.COM