Securing a future for anonymous functions in Python

Discussion in 'Python' started by Nick Coghlan, Dec 30, 2004.

  1. Nick Coghlan

    Nick Coghlan Guest

    GvR has commented that he want to get rid of the lambda keyword for Python 3.0.
    Getting rid of lambda seems like a worthy goal, but I'd prefer to see it dropped
    in favour of a different syntax, rather than completely losing the ability to
    have anonymous functions.

    Anyway, I'm looking for feedback on a def-based syntax that came up in a recent
    c.l.p discussion:
    http://boredomandlaziness.skystorm.net/2004/12/anonymous-functions-in-python.html

    Cheers,
    Nick.

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

  2. Nick Coghlan

    Paul Rubin Guest

    Nick Coghlan <> writes:
    > Anyway, I'm looking for feedback on a def-based syntax that came up in
    > a recent c.l.p discussion:


    Looks like just an even more contorted version of lambda. It doesn't
    fix lambda's main deficiency which is inability to have several
    statements in the anonymous function.
     
    Paul Rubin, Dec 30, 2004
    #2
    1. Advertising

  3. Nick Coghlan

    Nick Coghlan Guest

    Paul Rubin wrote:
    > Nick Coghlan <> writes:
    >
    >>Anyway, I'm looking for feedback on a def-based syntax that came up in
    >>a recent c.l.p discussion:

    >
    >
    > Looks like just an even more contorted version of lambda. It doesn't
    > fix lambda's main deficiency which is inability to have several
    > statements in the anonymous function.


    Do you consider generator expressions or list comprehensions deficient because
    they don't allow several statements in the body of the for loop?

    Cheers,
    Nick.

    --
    Nick Coghlan | | Brisbane, Australia
    ---------------------------------------------------------------
    http://boredomandlaziness.skystorm.net
     
    Nick Coghlan, Dec 30, 2004
    #3
  4. Nick Coghlan

    John Roth Guest

    "Nick Coghlan" <> wrote in message
    news:...
    > GvR has commented that he want to get rid of the lambda keyword for Python
    > 3.0. Getting rid of lambda seems like a worthy goal, but I'd prefer to see
    > it dropped in favour of a different syntax, rather than completely losing
    > the ability to have anonymous functions.
    >
    > Anyway, I'm looking for feedback on a def-based syntax that came up in a
    > recent c.l.p discussion:
    > http://boredomandlaziness.skystorm.net/2004/12/anonymous-functions-in-python.html
    >
    > Cheers,
    > Nick.


    I think it's rather baroque, and I agree with Paul Ruben
    that it needs multiple statement capability.

    The syntax I prefer (and I don't know if it's actually been
    suggested before) is to use braces, that is { and }.

    In other words, an anonymous function looks like:
    {p1, p2, p3 |
    stmt1
    stmt2
    }

    There are two reasons for using braces. One is
    that it's the common syntax for blocks in a large number
    of languages. The other is that it should be relatively
    easy to disambiguate from dictionary literals, which are
    the only other current use of braces.

    The parameter list is optional, as is the bar ending
    the list. The reason for the bar instead of a colon
    is to help the parser in the case of a single parameter,
    which would look like the beginning of a dictionary
    literal. If the parser doesn't need the help, then a colon
    would be more consistent, hence better.

    A second issue is indentation. I'd set the indentation
    boundary wherever the _second_ line of the construct
    starts, as long as it's to the right of the prior
    indentation boundary. The unfortunate part of this, and one of the
    major stumbling blocks, is that it might take some
    significant reconceptualizing of the lexer and parser,
    which currently isn't set up to shift from expression
    back to statement mode and then return to expression
    mode.

    John Roth

    > --
    > Nick Coghlan | | Brisbane, Australia
    > ---------------------------------------------------------------
    > http://boredomandlaziness.skystorm.net
     
    John Roth, Dec 30, 2004
    #4
  5. Nick Coghlan

    Ian Bicking Guest

    John Roth wrote:
    > The syntax I prefer (and I don't know if it's actually been
    > suggested before) is to use braces, that is { and }.
    >
    > In other words, an anonymous function looks like:
    > {p1, p2, p3 |
    > stmt1
    > stmt2
    > }


    What's the advantage of something like that over the non-anonymous
    equivalent:

    def some_func(p1, p2, p3):
    stmt1
    stmt2

    I appreciate some of the motivation, but merely avoiding giving
    something a name doesn't seem like a laudible goal.

    The one motivation I can see for function expressions is
    callback-oriented programming, like:

    get_web_page(url,
    when_retrieved={page |
    give_page_to_other_object(munge_page(page))})

    The problem with the normal function in this case is the order of
    statements is reversed:

    def when_retrieved_callback(page):
    give_page_to_other_object(munge_page(page))
    get_web_page(url, when_retrieved=when_retrieved_callback)

    Oh, and you have to type the name twice, which is annoying. For most
    other functional programming constructs, list (and not generator)
    comprehensions work well enough, and the overhead of naming functions
    just isn't that big a deal.

    I think this specific use case -- defining callbacks -- should be
    addressed, rather than proposing a solution to something that isn't
    necessary. Which is to say, no one *needs* anonymous functions; people
    may need things which anonymous functions provide, but maybe there's
    other ways to provide the same thing. Decorator abuse, for instance ;)

    def get_web_page_decorator(url):
    def decorator(func):
    return get_web_page(url, when_retrieved=func)
    return decorator

    @get_web_page_decorator(url)
    def when_retrieved(page):
    give_page_to_other_object(munge_page(page))

    Or even (given a partial function as defined in some PEP, the number of
    which I don't remember):

    @partial(get_web_page, url)
    def when_retrieved(page):
    give_page_to_other_object(munge_page(page))

    It's okay not to like this proposal, I don't think I'm really serious.
    But I do think there's other ways to approach this. Function
    expressions could get really out of hand, IMHO, and could easily lead to
    twenty-line "expressions". That's aesthetically incompatible with
    Python source, IMHO.

    --
    Ian Bicking / / http://blog.ianbicking.org
     
    Ian Bicking, Dec 30, 2004
    #5
  6. Nick Coghlan

    Roy Smith Guest

    Ian Bicking <> wrote:
    > I think this specific use case -- defining callbacks -- should be
    > addressed, rather than proposing a solution to something that isn't
    > necessary. Which is to say, no one *needs* anonymous functions; people
    > may need things which anonymous functions provide, but maybe there's
    > other ways to provide the same thing. Decorator abuse, for instance ;)


    I'm not a big functional programming fan, so it should not come as a
    surprise that I don't often use lambda. The one place I do use it is in
    unit tests, where assertRaises() requires a callable. If what you're
    testing is an expression, you need to wrap it in a lambda.

    I suppose you could call this a special case of a callback.
     
    Roy Smith, Dec 30, 2004
    #6
  7. John> In other words, an anonymous function looks like:
    John> {p1, p2, p3 |
    John> stmt1
    John> stmt2
    John> }

    John> There are two reasons for using braces. One is that it's the
    John> common syntax for blocks in a large number of languages.

    Yeah, but it's not how blocks are spelled in Python. As Nick pointed out on
    his blog, allowing statements within expressions risks making code more
    difficult to read and understand.

    People keep trying to make Python something it is not. It is not
    fundamentally an expression-only language like Lisp, nor is it an
    expression-equals-statement language like C. There are good reasons why
    Guido chose the relationship between simple statements, compound statements
    and expressions that he did, readability and error avoidance being key.

    Skip
     
    Skip Montanaro, Dec 30, 2004
    #7
  8. Nick Coghlan

    Carl Banks Guest

    Nick Coghlan wrote:
    > GvR has commented that he want to get rid of the lambda keyword for

    Python 3.0.
    > Getting rid of lambda seems like a worthy goal, but I'd prefer to see

    it dropped
    > in favour of a different syntax, rather than completely losing the

    ability to
    > have anonymous functions.


    I shall either coin or reuse a new term here: "premature optimization
    of the Python language."

    (Please note that the word premature is not intended to be an accurate
    description, but irony by analogy, so spare me any semantic
    nitpicking.)

    In much the same way that programmers often spend a lot of time
    optimizing parts of their program that will yield very minor dividends,
    while they could have spent that time working on other things that will
    pay off a lot, many of the wannabe language designers here are spending
    a lot of time on aspects of the language for which any improvement
    would only pay small dividends.

    I think the worry about anonymous functions is one of the most
    widespread cases of "premature optimization of the Python Language."
    One could argue about the various benefits of particular choices, maybe
    even make a convincing case that one is best in accord with the design
    goals of Python; but in the end, the divends are small compared to
    improving other aspects of the language.


    --
    CARL BANKS
     
    Carl Banks, Dec 30, 2004
    #8
  9. Nick Coghlan

    David Bolen Guest

    Ian Bicking <> writes:

    > The one motivation I can see for function expressions is
    > callback-oriented programming, like:
    >
    > get_web_page(url,
    > when_retrieved={page |
    > give_page_to_other_object(munge_page(page))})


    This is my primary use case for lambda's nowadays as well - typically
    just to provide a way to convert the input to a callback into a call
    to some other routine. I do a lot of Twisted stuff, whose deferred
    objects make heavy use of single parameter callbacks, and often you
    just want to call the next method in sequence, with some minor change
    (or to ignore) the last result.

    So for example, an asynchronous sequence of operations might be like:

    d = some_deferred_function()
    d.addCallback(lambda x: next_function())
    d.addCallback(lambda blah: third_function(otherargs, blah))
    d.addCallback(lambda x: last_function())

    which to me is more readable (in terms of seeing the sequence of
    operations being performed in their proper order), then something like:

    def cb_next(x):
    return next_function()
    def cb_third(blah, otherargs):
    return third_function(otherargs, blah)
    def cb_last(x):
    return last_function()

    d = some_deferred_function()
    d.addCallback(cb_next)
    d.addCallback(cb_third, otherargs)
    d.addCallback(cb_next)

    which has an extra layer of naming (the callback functions), and
    requires more effort to follow the flow of what is really just a simple
    sequence of three functions being called.

    > I think this specific use case -- defining callbacks -- should be
    > addressed, rather than proposing a solution to something that isn't
    > necessary. (...)


    I'd be interested in this approach too, especially if it made it simpler
    to handle simple manipulation of callback arguments (e.g., since I often
    ignore a successful prior result in a callback in order to just move on
    to the next function in sequence).

    -- David
     
    David Bolen, Dec 30, 2004
    #9
  10. On Thu, 30 Dec 2004 23:28:46 +1000, Nick Coghlan <> wrote:

    >GvR has commented that he want to get rid of the lambda keyword for Python 3.0.
    >Getting rid of lambda seems like a worthy goal, but I'd prefer to see it dropped
    >in favour of a different syntax, rather than completely losing the ability to
    >have anonymous functions.
    >
    >Anyway, I'm looking for feedback on a def-based syntax that came up in a recent
    >c.l.p discussion:
    >http://boredomandlaziness.skystorm.net/2004/12/anonymous-functions-in-python.html
    >

    Nit: You didn't try the code you posted ;-)

    >>> funcs = [(lambda x: x + i) for i in range(10)]
    >>>
    >>> def incrementors():

    ... for i in range(10):
    ... def incrementor(x):
    ... return x + i
    ... yield incrementor
    ...
    >>> #funcs = list(incrementors)

    ... funcs2 = list(incrementors())
    >>>
    >>> for f in funcs: print f(0),

    ...
    9 9 9 9 9 9 9 9 9 9
    >>> for f in funcs2: print f(0),

    ...
    9 9 9 9 9 9 9 9 9 9

    This is an easy trap to fall into, so if the new lambda-substitute could
    provide a prettier current-closure-variable-value capture than passing a dummy default
    value or nesting another def and passing the value in, to provide a private closure for each,
    that might be something to think about.

    IMO an anonymous def that exactly duplicates ordinary def except for leaving out
    the function name and having a local indentation context would maximize flexibility
    and also re-use of compiler code. People could abuse it, but that's already true
    of many Python features.

    From your web page:
    ----
    def either(condition, true_case, false_case):
    if condition:
    return true_case()
    else:
    return false_case()

    print either(A == B, (def "A equals B"), (def "A does not equal B"))
    either(thefile, (def thefile.close()), (def 0))
    ----

    I'd rather see :)something) than (def something) for this special case,
    but the full-fledged anonymous def would spell it thus:

    print either(A == B, (def():return "A equals B"), (def(): return "A does not equal B"))
    either(thefile, (def(): return thefile.close()), (def(): return 0))

    BTW,

    funcs = [(lambda x: x + i) for i in range(10)]

    might be spelled

    funcs = [(def(x, i=i): return x + i) for i in range(10)]

    or optionally

    funcs = [(
    def(x, i=i):
    return x + i
    ) for i in range(10)]

    or

    funcs = [(def(x, i=i):
    return x + i) for i in range(10)]
    or
    funcs = [(def(x, i=i):
    return x + i)
    for i in range(10)]
    or
    funcs = [def(x, i=i):
    return x + i
    for i in range(10)]
    or
    funcs = [
    def(x, i=i):
    return x + i
    for i in range(10)]

    and so on. (the def defines the indentation base if the suite is indented, and the closing ')'
    terminates the anonymous def explicitly, or a dedent to the level of the def or less can do it,
    as in the last two examples).

    This one

    (def f(a) + g(b) - h(c) from (a, b, c))

    would be spelled (if I undestand your example)

    (def(a, b, c): return f(a)+g(b)+h(c))

    which seems to me familiar and easy to understand.

    BTW, there are old threads where this and other formats were discussed. I am still
    partial to the full anonymous def with nesting indentation rules. Syntactic sugar
    could be provided for useful abbreviations (that could possibly be expanded by the
    tokenizer -- re which possibilities I haven't seen any discussion than my own
    recent post, BTW), but I'd like the full capability.

    Regards,
    Bengt Richter
     
    Bengt Richter, Dec 30, 2004
    #10
  11. Nick Coghlan

    John Roth Guest

    "Ian Bicking" <> wrote in message
    news:...
    > John Roth wrote:
    >> The syntax I prefer (and I don't know if it's actually been
    >> suggested before) is to use braces, that is { and }.
    >>
    >> In other words, an anonymous function looks like:
    >> {p1, p2, p3 |
    >> stmt1
    >> stmt2
    >> }

    >
    > What's the advantage of something like that over the non-anonymous
    > equivalent:
    >
    > def some_func(p1, p2, p3):
    > stmt1
    > stmt2
    >
    > I appreciate some of the motivation, but merely avoiding giving something
    > a name doesn't seem like a laudible goal.


    Actually, it is a laudable goal. It's always easier to understand
    something when it's right in front of your face than if it's
    off somewhere else.

    This, of course, trades off with two other forces: avoiding
    repetition and making the whole thing small enough to
    understand.

    So the niche is small, single use functions. The problem
    with lambdas is that they're restricted to one expression,
    which is too small.

    Languages that are designed with anonymous functions
    in mind use them very heavily. Smalltalk is the standard
    example, and it's also one of the major (possibly the
    only) attraction Ruby has over Python.

    Python isn't designed that way, which restricts their
    utility to a much smaller niche than otherwise.

    > The one motivation I can see for function expressions is callback-oriented
    > programming ...


    Well, that's true, but that's a very global statement:
    when you pass a function into another routine, it's
    essentially a callback.

    ....

    > Function expressions could get really out of hand, IMHO, and could easily
    > lead to twenty-line "expressions". That's aesthetically incompatible with
    > Python source, IMHO.


    Anything can get out of hand; there's no way of legislating
    good style without restricting the language so much that it
    becomes unusable for anything really interesting. Even then
    it doesn't work: see COBOL as a really good example of
    good intentions gone seriously wrong.

    Have you ever programmed in a language that does use
    anonymous functions extensively like Smalltalk?

    John Roth
    >
    > --
    > Ian Bicking / / http://blog.ianbicking.org
     
    John Roth, Dec 30, 2004
    #11
  12. Nick Coghlan

    Jeff Shannon Guest

    David Bolen wrote:

    >>I think this specific use case -- defining callbacks -- should be
    >>addressed, rather than proposing a solution to something that isn't
    >>necessary. (...)
    >>
    >>

    >
    >I'd be interested in this approach too, especially if it made it simpler
    >to handle simple manipulation of callback arguments (e.g., since I often
    >ignore a successful prior result in a callback in order to just move on
    >to the next function in sequence).
    >
    >


    It seems to me that what most people *actually* want, when asking for
    lambdas, is a quicker and more convenient way to get closures. (At
    least, that's what the vast majority of examples of lambda use seem to
    be for.) Perhaps one could get a bit more traction by looking for
    improved closure syntax instead of focusing on the anonymous function
    aspect.

    All of the suggestions for anonymous multiline functions (with embedded
    indentation) seem to me to miss what seems to me to be the only
    significant benefit of lambda -- its ability to be used in-line without
    creating a huge ugly tangle. (I'd argue that lambdas create a *small*
    ugly tangle, but apparently that's just me. ;) ) Lambdas do have some
    value in defining callbacks, but that value derives almost exclusively
    from the fact that they are in-line (rather than a few lines above).
    Mimicking function-def indentation inside of another function's arglist
    strikes me as an abomination just waiting to happen; in comparison, the
    need to type a name twice seems trivial.

    As a result, it seems to me that, rather than generalize lambdas into
    "full" anonymous functions (with most of the negatives and few of the
    positives of lambda), it would be much better to specialize them further
    into inline-closure-creators, where they can serve a valuable purpose
    without quite as much risk of code pollution.

    Jeff Shannon
    Technician/Programmer
    Credit International
     
    Jeff Shannon, Dec 30, 2004
    #12
  13. On Thu, 30 Dec 2004 15:15:51 -0800, Jeff Shannon <> wrote:

    >David Bolen wrote:
    >
    >>>I think this specific use case -- defining callbacks -- should be
    >>>addressed, rather than proposing a solution to something that isn't
    >>>necessary. (...)
    >>>
    >>>

    >>
    >>I'd be interested in this approach too, especially if it made it simpler
    >>to handle simple manipulation of callback arguments (e.g., since I often
    >>ignore a successful prior result in a callback in order to just move on
    >>to the next function in sequence).
    >>
    >>

    >
    >It seems to me that what most people *actually* want, when asking for
    >lambdas, is a quicker and more convenient way to get closures. (At
    >least, that's what the vast majority of examples of lambda use seem to
    >be for.) Perhaps one could get a bit more traction by looking for
    >improved closure syntax instead of focusing on the anonymous function
    >aspect.

    Not sure what you mean by closure here. To me it means the necessary
    external environment needed to be captured for use by a function definition
    getting exported from its definition environment. I.e., it is something
    a function uses, and part of the function definition, but it isn't the
    function itself. I would compare a closure more to a callable class instance's
    self attributes, except that the latter are more flexible.

    In fact, for a callback, a constructor call creating a suitable
    callable class instance could sometimes work well as a substitute
    for a lambda expression, ISTM. (I.e., when it is not important to
    show the code in line, and the differences are in initialization parameters
    rather than code).

    >
    >All of the suggestions for anonymous multiline functions (with embedded
    >indentation) seem to me to miss what seems to me to be the only
    >significant benefit of lambda -- its ability to be used in-line without
    >creating a huge ugly tangle. (I'd argue that lambdas create a *small*
    >ugly tangle, but apparently that's just me. ;) ) Lambdas do have some
    >value in defining callbacks, but that value derives almost exclusively
    >from the fact that they are in-line (rather than a few lines above).

    They do let you define _code_ inline, which a constructor call doesn't do
    (unless you pass a string to compile etc -- not cool).

    >Mimicking function-def indentation inside of another function's arglist
    >strikes me as an abomination just waiting to happen; in comparison, the
    >need to type a name twice seems trivial.

    Self-restraint can avoid abominations ;-)

    >
    >As a result, it seems to me that, rather than generalize lambdas into
    >"full" anonymous functions (with most of the negatives and few of the
    >positives of lambda), it would be much better to specialize them further
    >into inline-closure-creators, where they can serve a valuable purpose
    >without quite as much risk of code pollution.


    There's always the temptation to be enforcer when being persuader
    is not the easiest ;-)

    (BTW, again, by closure, do you really mean deferred-action-thingie?)

    Regards,
    Bengt Richter
     
    Bengt Richter, Dec 31, 2004
    #13
  14. Nick Coghlan

    Jeff Shannon Guest

    Bengt Richter wrote:

    > On Thu, 30 Dec 2004 15:15:51 -0800, Jeff Shannon <> wrote:
    >
    >>Mimicking function-def indentation inside of another function's arglist
    >>strikes me as an abomination just waiting to happen; in comparison, the
    >>need to type a name twice seems trivial.

    >
    > Self-restraint can avoid abominations ;-)


    It can, but given the prevalence of lambda abominations (such as the
    many that the Martellibot described among Cookbook submissions), is
    there any reason to believe that there would be *more* restraint in
    using a less-constrained feature?? :)

    >>As a result, it seems to me that, rather than generalize lambdas into
    >>"full" anonymous functions (with most of the negatives and few of the
    >>positives of lambda), it would be much better to specialize them further
    >>into inline-closure-creators, where they can serve a valuable purpose
    >>without quite as much risk of code pollution.

    >
    > (BTW, again, by closure, do you really mean deferred-action-thingie?)


    My understanding of "closure" (which may well be wrong, as I've
    inferred it entirely from past discussions on this newsgroup) is that
    it's a callable with some or all of its parameters already set; e.g.,

    def one_and(foo):
    def closure(arg):
    return foo(1, arg)
    return closure

    incr = one_and(operator.add)

    The function one_and() returns a closure, here bound to incr. It is
    essentially a (partially) deferred action thingy, if you want to use
    technical terms. ;) I suppose that one could look at it as the
    environment in which to call a given function, exported for later use...

    My thesis here is that one of the most common (legitimate) uses of
    lambda is as an adapter, to create an intermediary that allows a
    callable with a given signature to be used in places where a different
    signature is expected -- that is, altering the number or order of
    arguments passed to a given callable (and possibly also capturing the
    current value of some other variable in the process). I feel that
    it's more fruitful to focus on this "adapter" quality rather than
    focusing on the "anonymous function" quality.

    Jeff Shannon
    Technician/Programmer
    Credit International
     
    Jeff Shannon, Dec 31, 2004
    #14
  15. Nick Coghlan

    Nick Coghlan Guest

    Bengt Richter wrote:
    > This is an easy trap to fall into, so if the new lambda-substitute could
    > provide a prettier current-closure-variable-value capture than passing a dummy default
    > value or nesting another def and passing the value in, to provide a private closure for each,
    > that might be something to think about.


    I forgot about that little trap. . .

    Cheers,
    Nick.

    --
    Nick Coghlan | | Brisbane, Australia
    ---------------------------------------------------------------
    http://boredomandlaziness.skystorm.net
     
    Nick Coghlan, Dec 31, 2004
    #15
  16. Nick Coghlan

    Nick Coghlan Guest

    Carl Banks wrote:
    > Nick Coghlan wrote:
    > In much the same way that programmers often spend a lot of time
    > optimizing parts of their program that will yield very minor dividends,
    > while they could have spent that time working on other things that will
    > pay off a lot, many of the wannabe language designers here are spending
    > a lot of time on aspects of the language for which any improvement
    > would only pay small dividends.


    Whereas I see it as wannabe language designers only being able to tinker at the
    edges of Python, because GvR already got the bulk of the language right.
    Anonymous functions are the major core construct that doesn't 'fit right', so a
    disproportionate amount of time is spent playing with ideas about them.

    Cheers,
    Nick.

    --
    Nick Coghlan | | Brisbane, Australia
    ---------------------------------------------------------------
    http://boredomandlaziness.skystorm.net
     
    Nick Coghlan, Dec 31, 2004
    #16
  17. On Thu, 30 Dec 2004 17:39:06 -0800, Jeff Shannon <> wrote:

    >Bengt Richter wrote:
    >
    >> On Thu, 30 Dec 2004 15:15:51 -0800, Jeff Shannon <> wrote:
    >>
    >>>Mimicking function-def indentation inside of another function's arglist
    >>>strikes me as an abomination just waiting to happen; in comparison, the
    >>>need to type a name twice seems trivial.

    >>
    >> Self-restraint can avoid abominations ;-)

    >
    >It can, but given the prevalence of lambda abominations (such as the
    >many that the Martellibot described among Cookbook submissions), is
    >there any reason to believe that there would be *more* restraint in
    >using a less-constrained feature?? :)

    Maybe. If people are determined to overcome limitations that needn't exist,
    they are likely to invent horrible hacks ;-)

    >
    >>>As a result, it seems to me that, rather than generalize lambdas into
    >>>"full" anonymous functions (with most of the negatives and few of the
    >>>positives of lambda), it would be much better to specialize them further
    >>>into inline-closure-creators, where they can serve a valuable purpose
    >>>without quite as much risk of code pollution.

    >>
    >> (BTW, again, by closure, do you really mean deferred-action-thingie?)

    >
    >My understanding of "closure" (which may well be wrong, as I've
    >inferred it entirely from past discussions on this newsgroup) is that
    >it's a callable with some or all of its parameters already set; e.g.,
    >
    > def one_and(foo):
    > def closure(arg):
    > return foo(1, arg)
    > return closure
    >
    > incr = one_and(operator.add)
    >
    >The function one_and() returns a closure, here bound to incr. It is
    >essentially a (partially) deferred action thingy, if you want to use
    >technical terms. ;) I suppose that one could look at it as the
    >environment in which to call a given function, exported for later use...


    Quoting from "Essentials of Programming Languages" (Friedman, Wand, Haynes):
    (using *xxx yyy etc* for italics)
    """
    In order for a procedure to retain the bindings that its free variables had
    at the time it was created, it must be a *closed* package, independent of
    the environment in which it is used. Such a package is called a closure.
    In order to be self-contained, a closure must contain the procedure body,
    the list of formal parameters, and the bindings of its free variables.
    It is convenient to store the entire creation environment, rather than
    just the bindings of the free variables. We sometimes say the procedure
    *is closed over* or *closed in* its creation environment. We represent
    closures as records.
    """

    So it looks like you infer better than I remember, and attachment to
    faulty memory has led me to resist better inferences ;-/

    Closure is the name for the whole thing, apparently, not just the environment
    the procedure body needs, which was the aspect that I (mis)attached the name to.

    (Representing closures as records doesn't really belong in that paragraph IMO,
    since it is not really part of the definition there, just a choice in that stage
    of exposition in the book, using scheme-oriented examples. But I quoted verbatim.).

    On the subject CLtL finally (after some stuff beyond my current caffeine level) says,
    """
    The distinction between closures and other kinds of functions is somewhat pointless,
    actually, since Common Lisp defines no particular representation for closures and
    no way to distinguish between closures and non-closure functions. All that matters
    is that the rules of lexical scoping be obeyed.
    """
    I guess that clinches it ;-)

    Might be a good python glossary wiki entry.

    >
    >My thesis here is that one of the most common (legitimate) uses of
    >lambda is as an adapter, to create an intermediary that allows a
    >callable with a given signature to be used in places where a different
    >signature is expected -- that is, altering the number or order of
    >arguments passed to a given callable (and possibly also capturing the
    >current value of some other variable in the process). I feel that
    >it's more fruitful to focus on this "adapter" quality rather than
    >focusing on the "anonymous function" quality.
    >

    I see what you are saying (I think), but I think I'd still like a full
    anonymous def, whatever adapter you come up with. And I prefer to be persuaded ;-)

    Regards,
    Bengt Richter
     
    Bengt Richter, Dec 31, 2004
    #17
  18. Jeff Shannon wrote:
    > My thesis here is that one of the most common (legitimate) uses of
    > lambda is as an adapter, to create an intermediary that allows a
    > callable with a given signature to be used in places where a different
    > signature is expected -- that is, altering the number or order of
    > arguments passed to a given callable (and possibly also capturing the
    > current value of some other variable in the process). I feel that it's
    > more fruitful to focus on this "adapter" quality rather than focusing on
    > the "anonymous function" quality.


    Maybe the 'functional' module proposed in PEP 309[1] could provide such
    functions?

    py> def ignoreargs(func, nargs, *kwd_names):
    .... def _(*args, **kwds):
    .... args = args[nargs:]
    .... kwds = dict((k, kwds[k])
    .... for k in kwds if k not in kwd_names)
    .... return func(*args, **kwds)
    .... return _
    ....
    py> def f(x, y):
    .... print x, y
    ....
    py> ignoreargs(f, 2)(1, 2, 3, 4)
    3 4
    py> ignoreargs(f, 2, 'a', 'b')(1, 2, 3, 4, a=35, b=64)
    3 4

    Steve

    [1] http://python.fyxm.net/peps/pep-0309.html
     
    Steven Bethard, Dec 31, 2004
    #18
  19. Nick Coghlan

    Paul Rubin Guest

    (Bengt Richter) writes:
    > print either(A == B, (def "A equals B"), (def "A does not equal B"))
    > either(thefile, (def thefile.close()), (def 0))


    I'd really rather have some reasonable macro facility, than to resort
    to using anonymous functions and deferred evaluation for common things
    like that.
     
    Paul Rubin, Dec 31, 2004
    #19
  20. Nick Coghlan

    Ian Bicking Guest

    John Roth wrote:
    >> I appreciate some of the motivation, but merely avoiding giving
    >> something a name doesn't seem like a laudible goal.

    >
    > Actually, it is a laudable goal. It's always easier to understand
    > something when it's right in front of your face than if it's
    > off somewhere else.


    Naming the function doesn't move it far away. It changes the order (you
    have to define it before you use it), and it introduces a name.

    >> The one motivation I can see for function expressions is
    >> callback-oriented programming ...

    >
    > Well, that's true, but that's a very global statement:
    > when you pass a function into another routine, it's
    > essentially a callback.


    Sure, technically. But I'm thinking of real use cases. One I'm
    familiar with is things like map and filter. These are generally better
    handled with list expressions (and MUCH more readable as such, IMHO).
    Another is control structures, ala Ruby or Smalltalk. IMHO, we have all
    the control structures we need -- while, for, if. Most "novel" control
    structures in Ruby or Smalltalk are just another take on iterators. The
    exception being callbacks, and perhaps some other lazy evaluation
    situations (though outside of what I think of as "callbacks", I can't
    think of any lazy evaluation situations off the top of my head).

    So that's why I think callbacks are important; callbacks in the style of
    Twisted Deferred, GUI events, etc.

    >> Function expressions could get really out of hand, IMHO, and could
    >> easily lead to twenty-line "expressions". That's aesthetically
    >> incompatible with Python source, IMHO.

    >
    > Anything can get out of hand; there's no way of legislating
    > good style without restricting the language so much that it
    > becomes unusable for anything really interesting. Even then
    > it doesn't work: see COBOL as a really good example of
    > good intentions gone seriously wrong.


    OK, I should go further -- even a two-line expression (i.e., an
    expression that contains meaningful vertical whitespace) is
    aesthetically incompatible with Python source. Which covers any
    anonymous function that is more powerful than lambda. I'm not arguing
    that it can be abused, but more that it isn't any good even when it's
    not being abused.

    > Have you ever programmed in a language that does use
    > anonymous functions extensively like Smalltalk?


    Yep, I've done a fair amount of Smalltalk and Scheme programming. I
    don't expect Python to act like them. I appreciate the motivation, but
    I don't think their solution is the right one for Python.

    --
    Ian Bicking / / http://blog.ianbicking.org
     
    Ian Bicking, Dec 31, 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. Xiangliang Meng
    Replies:
    1
    Views:
    1,609
    Victor Bazarov
    Jun 21, 2004
  2. Jp Calderone
    Replies:
    8
    Views:
    314
    Steven Bethard
    Jan 1, 2005
  3. Reporter
    Replies:
    3
    Views:
    477
    Mike Schilling
    May 12, 2007
  4. Cristian
    Replies:
    66
    Views:
    1,109
    Bruno Desthuilliers
    Sep 24, 2007
  5. Replies:
    1
    Views:
    223
Loading...

Share This Page