Re: Is this a good use for lambda

Discussion in 'Python' started by Fredrik Lundh, Dec 19, 2004.

  1. Walter S. Leipold wrote:

    > I think that Charlie's point is that, when you use "def <name>", you have
    > <name> polluting your namespace. The whole program becomes harder to
    > understand because you can't ignore <name> anywhere, even if it was only
    > ever intended to be used in one place.


    Ahem. If you name the function, you can reuse the name (or just forget about it)
    as soon as you've used the function object.

    If you don't want to reuse the name because you might want to reuse the function
    object, you have to name it anyway.

    </F>
     
    Fredrik Lundh, Dec 19, 2004
    #1
    1. Advertising

  2. "Fredrik Lundh" <> writes:

    > Walter S. Leipold wrote:
    > > I think that Charlie's point is that, when you use "def <name>",
    > > you have <name> polluting your namespace. The whole program
    > > becomes harder to understand because you can't ignore <name>
    > > anywhere, even if it was only ever intended to be used in one
    > > place.

    > Ahem. If you name the function, you can reuse the name (or just
    > forget about it) as soon as you've used the function object.


    Sure, but mental pollution counts too IMO. What you write and what you
    read must go through your brain, including dummy variables. And next
    you start thinking how to "hide" it from your own mind (e.g. naming it
    "_my_local_func" or something as ugly as the leading underscores in
    it).

    And I think that it does, in fact, touch the innermost symbol table
    too, even if the case is optimized out by the compiler -- is it?

    Why do something for the sake of not actually having to do it?

    ***

    Anyway, personally, this namespace cluttering most often happens
    because lambda is only a single expression. If one could write a true
    function block into a lambda, there would be less cases where lambda
    doesn't suffice, really.

    Now, if lambda was more than an expr, dumping "lambda" keyword would
    be a convenient idea -- unnecessary keywords can make the language
    less clear in some cases. One could do with Python's plain and simple
    "def", like this:

    filter (def (x): x*2, myseq)

    (Disclaimer: Without thinking further I'm not sure whether the above
    syntax would be unique enough, Python grammar-wise.)


    br,
    S
     
    Simo Melenius, Dec 19, 2004
    #2
    1. Advertising

  3. Simo Melenius wrote:
    > Now, if lambda was more than an expr, dumping "lambda" keyword would
    > be a convenient idea -- unnecessary keywords can make the language
    > less clear in some cases. One could do with Python's plain and simple
    > "def", like this:
    >
    > filter (def (x): x*2, myseq)
    >
    > (Disclaimer: Without thinking further I'm not sure whether the above
    > syntax would be unique enough, Python grammar-wise.)


    If you'd like to think further about it, check the archves -- there's
    about a million different arguments about this. A recent brief one (2
    days ago):

    http://mail.python.org/pipermail/python-list/2004-December/255728.html

    Steve
     
    Steven Bethard, Dec 19, 2004
    #3
  4. Simo Melenius wrote:

    >> Ahem. If you name the function, you can reuse the name (or just
    >> forget about it) as soon as you've used the function object.

    >
    > Sure, but mental pollution counts too IMO. What you write and what you
    > read must go through your brain, including dummy variables. And next
    > you start thinking how to "hide" it from your own mind (e.g. naming it
    > "_my_local_func" or something as ugly as the leading underscores in
    > it).


    use something short, like "f". hopefully, a single character won't overload
    your brain.

    > And I think that it does, in fact, touch the innermost symbol table
    > too, even if the case is optimized out by the compiler -- is it?


    yes, but the overhead of keeping a local slot updated is very small,
    especially compared to all the work Python's doing to create a new
    function object.

    (or did you mean that you're trying to keep the entire symbol table
    in your head? I think my point was that you don't really have to do
    that; just concentrate on what's close to the code you're reading)

    > Why do something for the sake of not actually having to do it?


    not sure I parsed that one correctly, but when I name functions, I usually
    do that because it makes my code cleaner, more self-describing, gives it
    a better visual layout, makes it easier to modify/maintain, makes it easier
    to set breakpoints or add debugging statements, etc. "lambda blocks"
    can address some of that, but not all of it.

    </F>
     
    Fredrik Lundh, Dec 19, 2004
    #4
  5. On Sun, 19 Dec 2004 20:59:43 +0100, "Fredrik Lundh" <> wrote:

    >Walter S. Leipold wrote:
    >
    >> I think that Charlie's point is that, when you use "def <name>", you have
    >> <name> polluting your namespace. The whole program becomes harder to
    >> understand because you can't ignore <name> anywhere, even if it was only
    >> ever intended to be used in one place.

    >
    >Ahem. If you name the function, you can reuse the name (or just forget about it)
    >as soon as you've used the function object.
    >
    >If you don't want to reuse the name because you might want to reuse the function
    >object, you have to name it anyway.
    >

    Are you forgetting that all bindings are not directly name bindings as created by def? ;-)
    (See also various tkinter-related uses).

    >>> funs = [lambda:'one', lambda:'two', lambda:'three']
    >>> for use in xrange(2):

    ... for i in xrange(3):
    ... print '%susing fun[%s] => %r' %('re'*(use>0), i, funs())
    ...
    using fun[0] => 'one'
    using fun[1] => 'two'
    using fun[2] => 'three'
    reusing fun[0] => 'one'
    reusing fun[1] => 'two'
    reusing fun[2] => 'three'

    Regards,
    Bengt Richter
     
    Bengt Richter, Dec 20, 2004
    #5
  6. Bengt Richter wrote:

    >>Ahem. If you name the function, you can reuse the name (or just forget about it)
    >>as soon as you've used the function object.
    >>
    >>If you don't want to reuse the name because you might want to reuse the function
    >>object, you have to name it anyway.
    >>

    > Are you forgetting that all bindings are not directly name bindings as created by def? ;-)
    > (See also various tkinter-related uses).
    >
    > >>> funs = [lambda:'one', lambda:'two', lambda:'three']


    now you've used the function objects once each.

    > >>> for use in xrange(2):

    > ... for i in xrange(3):
    > ... print '%susing fun[%s] => %r' %('re'*(use>0), i, funs())


    and now you're using the data structure you built... at this point, it doesnt matter
    if the functions had distinct names to start with.

    (coming up with a contrived example where it matters is trivial, of course, but by
    then, we've moved into "whitespace" or "static typing leads to more reliable code"
    country)

    </F>
     
    Fredrik Lundh, Dec 20, 2004
    #6
  7. Fredrik Lundh

    Max M Guest

    The entity Fredrik Lundh wrote:

    </F>

    Isn't it about time you became xml avare, and changed that to:

    <f/>

    ?



    --

    hilsen/regards Max M, Denmark

    http://www.mxm.dk/
    IT's Mad Science
     
    Max M, Dec 20, 2004
    #7
  8. Max M wrote:
    > Isn't it about time you became xml avare, and changed that to:
    >
    > <f/>


    That makes no sense.
    --
    Michael Hoffman
     
    Michael Hoffman, Dec 20, 2004
    #8
  9. Fredrik Lundh

    Steve Holden Guest

    Michael Hoffman wrote:

    > Max M wrote:
    >
    >> Isn't it about time you became xml avare, and changed that to:
    >>
    >> <f/>

    >
    >
    > That makes no sense.


    Yeah, but give the guy a break, we've all made feeble attempts at humor
    from time to time. You realize, I suppose, that it's a reference to the
    fact that XHTML uses lower-case tags and allows self-closure with a
    trailing slash after the tag name?

    let's-keep-that-christmas-spirit-coming-ly y'rs - steve
    --
    Steve Holden http://www.holdenweb.com/
    Python Web Programming http://pydish.holdenweb.com/
    Holden Web LLC +1 703 861 4237 +1 800 494 3119
     
    Steve Holden, Dec 20, 2004
    #9
  10. "Fredrik Lundh" <> writes:

    > Simo Melenius wrote:
    > > Sure, but mental pollution counts too IMO. What you write and what you
    > > read must go through your brain, including dummy variables. And next
    > > you start thinking how to "hide" it from your own mind (e.g. naming it
    > > "_my_local_func" or something as ugly as the leading underscores in
    > > it).

    > use something short, like "f". hopefully, a single character won't overload
    > your brain.


    I've heard some brain can tackle even Java's overly verbose syntax, it
    just depends on one's mind set how the verbosity is perceived: some
    find it a disrupting must, some like spending time writing things for
    which another programmer would've written a code generator by now.

    Elaborating more: Yes, naming functions that are only used once is
    minor nuisance (but still something I hope to get rid of eventually).
    In a level, it's probably similar to how whitespace at the end of the
    lines bogs some people -- that stuff just doesn't need to be there, so
    the text feels cluttered. (For _that_, Emacs luckily has its
    whitespace mode.. :))

    ***

    Like someone pointed, using _ is a good convention for throwaways. The
    fact that such a convention exist just emphasizes that it _is_ an
    issue from which people try to sway away.

    > > And I think that it does, in fact, touch the innermost symbol table

    > yes, but the overhead of keeping a local slot updated is very small,


    Sure; though I considered it more of a conceptual issue rather than a
    performance one.


    br,
    S
     
    Simo Melenius, Dec 20, 2004
    #10
  11. Fredrik Lundh

    Max M Guest

    Steve Holden wrote:
    >> Max M wrote:
    >>> Isn't it about time you became xml avare, and changed that to:
    >>> <f/>

    >
    > Yeah, but give the guy a break, we've all made feeble attempts at humor
    > from time to time.


    Hey, what's wrong with a little nørd humor...

    I just found it amusing that somenone like Frederik Lundh, who has
    written xml stuff like ElementTree, uses something that reminds of an
    old HTML tag as a sig.


    > You realize, I suppose, that it's a reference to the
    > fact that XHTML uses lower-case tags and allows self-closure with a
    > trailing slash after the tag name?
    >
    > let's-keep-that-christmas-spirit-coming-ly y'rs - steve


    :) yes please.


    --

    hilsen/regards Max M, Denmark

    http://www.mxm.dk/
    IT's Mad Science
     
    Max M, Dec 20, 2004
    #11

  12. > I just found it amusing that somenone like Frederik Lundh, who has
    > written xml stuff like ElementTree, uses something that reminds of an old HTML tag as a sig.


    it's a perfectly valid XML end tag. locating the start tag is left as an exercise...

    </F>
     
    Fredrik Lundh, Dec 20, 2004
    #12
  13. Simo Melenius wrote:

    >> use something short, like "f". hopefully, a single character won't overload
    >> your brain.

    >
    > I've heard some brain can tackle even Java's overly verbose syntax


    I find that hard to believe. Are you sure they're not relying on eclipse, or some
    other body part?

    > Like someone pointed, using _ is a good convention for throwaways. The
    > fact that such a convention exist just emphasizes that it _is_ an
    > issue from which people try to sway away.


    The drawback is that _ is commonly used for translations:

    http://docs.python.org/lib/node317.html

    (using "f" for some function is of course well-established also outside programming,
    as your nearest dictionary or encyclopedia will tell you. "x" and "i" are other letters
    for which programming use often matches established meanings...)

    </F>
     
    Fredrik Lundh, Dec 20, 2004
    #13
  14. Fredrik Lundh

    Alan G Isaac Guest

    I need a clarification of the argument.
    Are the opponents saying that I should not be able to:

    def compose(list_of_functions): return reduce(lambda f, g: lambda x:
    f(g(x)), list_of_functions)

    In a nutshell: why?
    And may I see the proposed "better" replacement for function composition.

    Thanks,
    Alan Isaac
     
    Alan G Isaac, Dec 21, 2004
    #14
  15. Alan G Isaac wrote:

    > Are the opponents saying that I should not be able to:
    >
    > def compose(list_of_functions): return reduce(lambda f, g: lambda x:
    > f(g(x)), list_of_functions)
    >
    > In a nutshell: why?


    I was about to reply, but I couldn't figure out what the piece of code does
    in the allotted timeframe.

    </F>
     
    Fredrik Lundh, Dec 21, 2004
    #15
  16. Alan G Isaac wrote:
    > I need a clarification of the argument.
    > Are the opponents saying that I should not be able to:
    >
    > def compose(list_of_functions): return reduce(lambda f, g: lambda x:
    > f(g(x)), list_of_functions)


    Personally, I think something like this is a place where lambdas are
    probably better than named functions. Still, you can do this without
    lambdas:

    def compose(list_of_functions):
    def compose2(f, g):
    def func(x):
    return f(g(x))
    return func
    return reduce(compose2, list_of_functions)

    > And may I see the proposed "better" replacement for function composition.


    Whether this is better or not, I don't know.

    --
    "Codito ergo sum"
    Roel Schroeven
     
    Roel Schroeven, Dec 21, 2004
    #16
  17. Replying to myself, with a simpler version:

    Roel Schroeven wrote:
    > Alan G Isaac wrote:
    >> def compose(list_of_functions): return reduce(lambda f, g: lambda x:
    >> f(g(x)), list_of_functions)

    >
    > def compose(list_of_functions):
    > def compose2(f, g):
    > def func(x):
    > return f(g(x))
    > return func
    > return reduce(compose2, list_of_functions)


    def compose(lof):
    def func(x):
    for f in reversed(lof):
    x = f(x)
    return x
    return func

    Still not sure what version is best though.

    --
    "Codito ergo sum"
    Roel Schroeven
     
    Roel Schroeven, Dec 21, 2004
    #17
  18. Fredrik Lundh

    Nick Coghlan Guest

    Alan G Isaac wrote:
    > I need a clarification of the argument.
    > Are the opponents saying that I should not be able to:
    >
    > def compose(list_of_functions): return reduce(lambda f, g: lambda x:
    > f(g(x)), list_of_functions)


    As things stand, I can live with lambda. However, if something can't be said in
    a single expression, then it's too complicated to be embedded inside another
    statement and have the whole remain even remotely readable.

    Even the above example is impossible to parse easily unless you happen to
    recognise that the 'compose' means 'function composition'. (cf. Fredrik's
    reaction. . .)

    > In a nutshell: why?


    I dislike the use of lambda here, because it isn't very readable for most
    people, and readability counts. To actually understand what this code does, I
    had to rewrite it as I have below.

    To parse a statement using lambdas and figure out what it does, one almost *has*
    to assign a mental name to each lambda. Why should every reader of the code have
    to go to that effort, when the author of the code can do it once, and provide
    premade mental handles for every code reader to come after them?

    > And may I see the proposed "better" replacement for function composition.


    Moving to a programming world where whitespace and typed characters are so cheap
    as to be practically free:

    def compose(list_of_functions):
    def compose_pair(f, g):
    def composed_pair(x):
    f(g(x))
    return composed_pair
    return reduce(compose_pair, list_of_functions)

    The advantage of this version is that what it does is fairly obvious, even to
    someone that doesn't often use the term 'function composition' (like, say, me -
    I know what it means, but it doesn't spring to mind naturally).

    Moving on, I'd suggest that for any significant list of functions, the
    performance of the recursive version is going to be lousy, and I'd rewrite it
    with the iterative version:

    def compose(list_of_functions):
    application_order = reversed(list_of_functions)
    def composed(x):
    for f in application_order:
    x = f(x)
    return x
    return composed

    With this last version, even people that don't use functional programming at all
    can see immediately what the function is doing, including what the order of
    application is for the functions that combine to give the overall function
    composition (I had to go look up the precise operation of reduce() to be sure I
    had the order of application for function composition correct). The initial
    creation is going to be much faster (creating a single function object, rather
    than a big stack of them), and the actual invocation is going to be faster
    (since it's a simple iteration, rather than a big chain of recursive function
    calls).

    What are the disavantages of my final version?

    1. It will deeply offend the aesthetic sensibilities of any functional purists
    in the audience.

    2. It no longer directly implements the theoretical concept of function
    composition (although it has the same effect).

    From a real world programming point of view, though, it's self-documenting,
    runs faster and uses less memory, so it's really a pure win.

    Cheers,
    Nick.

    --
    Nick Coghlan | | Brisbane, Australia
    ---------------------------------------------------------------
    http://boredomandlaziness.skystorm.net
     
    Nick Coghlan, Dec 21, 2004
    #18
  19. Nick Coghlan wrote:
    > def compose(list_of_functions):
    > application_order = reversed(list_of_functions)
    > def composed(x):
    > for f in application_order:
    > x = f(x)
    > return x
    > return composed


    reversed returns an iterator to the list in reverse order, not a copy of
    the list:

    >>> lst = range(10)
    >>> riter = reversed(lst)
    >>> list(riter)

    [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
    >>> list(riter)

    []

    so you either need to call reversed each time in 'composed' or copy the
    list and call reverse.

    Steve
     
    Steven Bethard, Dec 21, 2004
    #19
  20. Fredrik Lundh

    Nick Coghlan Guest

    Steven Bethard wrote:
    > Nick Coghlan wrote:
    >
    >> def compose(list_of_functions):
    >> application_order = reversed(list_of_functions)
    >> def composed(x):
    >> for f in application_order:
    >> x = f(x)
    >> return x
    >> return composed


    > so you either need to call reversed each time in 'composed' or copy the
    > list and call reverse.


    These iterator thingies sure are handy most of the time, but occasionally. . . I
    suspect the iterator (e.g. reversed()) vs list (e.g. sorted()) distinction is
    going to end up on a few of those 'Python Gotchas' pages.

    Ah well, at least I caught the 'return x' that was missing from my first draft
    version :)

    Corrected version:

    def compose(functions):
    application_order = list(functions)
    application_order.reverse()
    def composed(x)
    for f in application_order:
    x = f(x)
    return x
    return composed

    Cheers,
    Nick.

    P.S. For the curious:

    C:\>python -m timeit -s "x = range(10000)" "y = x[:]; y.reverse()"
    10000 loops, best of 3: 102 usec per loop

    C:\>python -m timeit -s "x = range(10000)" "y = list(x); y.reverse()"
    10000 loops, best of 3: 100 usec per loop

    C:\>python -m timeit -s "x = range(10000)" "y = list(reversed(x))"
    10000 loops, best of 3: 166 usec per loop

    --
    Nick Coghlan | | Brisbane, Australia
    ---------------------------------------------------------------
    http://boredomandlaziness.skystorm.net
     
    Nick Coghlan, Dec 21, 2004
    #20
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Roy Smith

    Finally found a use for lambda!

    Roy Smith, Sep 15, 2003, in forum: Python
    Replies:
    9
    Views:
    347
    Follower
    Sep 16, 2003
  2. Charlie Taylor

    Is this a good use for lambda

    Charlie Taylor, Dec 17, 2004, in forum: Python
    Replies:
    4
    Views:
    286
    Michael Hoffman
    Dec 18, 2004
  3. Roman Suzi
    Replies:
    13
    Views:
    608
    Bengt Richter
    Jan 7, 2005
  4. Steve Dogers

    lambda vs non-lambda proc

    Steve Dogers, Mar 30, 2009, in forum: Ruby
    Replies:
    1
    Views:
    178
    Sean O'Halpin
    Mar 30, 2009
  5. Haochen Xie
    Replies:
    4
    Views:
    245
    Haochen Xie
    Mar 17, 2013
Loading...

Share This Page