better lambda support in the future?

Discussion in 'Python' started by Jason Zheng, Dec 17, 2004.

  1. Jason Zheng

    Jason Zheng Guest

    I'm wondering why python still has limited lambda support. What's
    stopping the developers of python to support more lisp-like lambda function?
    Jason Zheng, Dec 17, 2004
    #1
    1. Advertising

  2. Jason Zheng

    Guest

    Lambda functions will become obsolette in the nearest future. This is
    the PLAN.
    , Dec 17, 2004
    #2
    1. Advertising

  3. Jason Zheng wrote:
    > I'm wondering why python still has limited lambda support. What's
    > stopping the developers of python to support more lisp-like lambda
    > function?


    This comes up every few weeks on the list. If you haven't already,
    check the archives in Google for 'anonymous def' or 'anonymous
    function'. The usual response to this question is something along the
    lines of "if it's good enough to create a function for, it's good enough
    to name".

    One of the other big reasons for this type of proposal never making it
    far is that, so far, no one has found a syntax that everyone (or even
    most people) like. You end up with things like:

    x = func or lambda x, y:
    # body of lambda func
    # indented here

    or

    x = func or lambda x, y:
    # body of lambda func
    # indented here

    or

    x = func or lambda x, y {
    # body of lamda func indented
    # however you want...
    }

    or any thousand other varieties.

    Even if you could settle the syntax issue, once you've decided that you
    really do need a true block in an anonymous function, you're not really
    saving much space by not declaring it:

    def f(*args):
    # body line 1
    # body line 2
    # ...
    # body line N
    x = func or f

    v.s.

    x = func or lambda *args:
    # body line 1
    # body line 2
    # ...
    # body line N

    so, you save a single line, which is only 1 Nth of the size of your
    function (where N is the number of lines in your function body). For a
    single or double line function, these savings may be more substantial,
    but chances are if your function is only one or two lines, it can be
    written as an expression anyway (e.g. using LCs or GEs)...


    Do check the archives -- there are a lot of discussions on this topic,
    but hopefully the brief commentary above will give you something of an
    overview.

    Steve
    Steven Bethard, Dec 17, 2004
    #3
  4. Steven Bethard wrote:

    > Even if you could settle the syntax issue, once you've decided that you really do need a true
    > block in an anonymous function, you're not really saving much space by not declaring it:
    >
    > def f(*args):
    > # body line 1
    > # body line 2
    > # ...
    > # body line N
    > x = func or f
    >
    > v.s.
    >
    > x = func or lambda *args:
    > # body line 1
    > # body line 2
    > # ...
    > # body line N


    you meant:

    def x(*args):
    # body line 1
    # body line 2
    # ...
    # body line N

    v.s.

    x = func or lambda *args:
    # body line 1
    # body line 2
    # ...
    # body line N

    right?

    </F>
    Fredrik Lundh, Dec 17, 2004
    #4
  5. Jason Zheng

    Jason Zheng Guest

    Steven Bethard wrote:
    > Jason Zheng wrote:
    >
    >> I'm wondering why python still has limited lambda support. What's
    >> stopping the developers of python to support more lisp-like lambda
    >> function?

    >
    >
    > This comes up every few weeks on the list. If you haven't already,
    > check the archives in Google for 'anonymous def' or 'anonymous
    > function'. The usual response to this question is something along the
    > lines of "if it's good enough to create a function for, it's good enough
    > to name".


    The true beauty of lambda function is not the convenience of creating
    functions without naming them. Lambda constructs truly enables
    higher-order function. For example, I can create a function A that
    returns a function B that does something interesting according to the
    arguments that I pass to function A.
    Jason Zheng, Dec 17, 2004
    #5
  6. Fredrik Lundh wrote:
    > Steven Bethard wrote:
    >
    >
    >>Even if you could settle the syntax issue, once you've decided that you really do need a true
    >>block in an anonymous function, you're not really saving much space by not declaring it:
    >>
    >>def f(*args):
    >> # body line 1
    >> # body line 2
    >> # ...
    >> # body line N
    >>x = func or f
    >>
    >>v.s.
    >>
    >>x = func or lambda *args:
    >> # body line 1
    >> # body line 2
    >> # ...
    >> # body line N

    >
    >
    > you meant:
    >
    > def x(*args):
    > # body line 1
    > # body line 2
    > # ...
    > # body line N
    >
    > v.s.
    >
    > x = func or lambda *args:
    > # body line 1
    > # body line 2
    > # ...
    > # body line N
    >
    > right?


    You're welcome to name the function whatever you want -- notice in my
    example that the function is used in the statement:

    x = func or f

    If you'd prefer the statement to read:

    x = func or x

    that's also fine. Depends on what exactly 'x' is, and whether or not it
    really makes sense for the function I called 'f' to have the same name
    as the variable called 'x'. It certainly may, but since I wasn't giving
    real code, I didn't want to commit to that.

    Perhaps a better example would have been something along the lines of:

    dict(a=lambda *args:
    # body 1
    ,
    b=lambda *args:
    # body 2
    ,
    c=lambda *args:
    # body 3
    )(values)

    v.s.

    def a_func(*args):
    # body 1
    def b_func(*args):
    # body 2
    def c_func(*args):
    # body 3
    dict(a=a_func, b=b_func, c=c_func)(values)

    where it's clear that I'm trying to use lambdas where expressions are
    required.

    I assume that the point you were trying to make is that:

    def f(*args):
    return expr

    is equivalent to

    f = lambda *args: expr

    ?

    Steve
    Steven Bethard, Dec 17, 2004
    #6
  7. True enough, but suppose you want a hash of anonymous functions as
    opposed to just a lexical? This is where lambas are nice to have.
    Totally agreed about a small use here and there, but they do have some
    use in dispatch tables, as they are a lot easier to read sometimes
    than very long case statements. Of course, this would require
    multi-line lambdas to exist...

    --Michael

    > I assume that the point you were trying to make is that:
    >
    > def f(*args):
    > return expr
    >
    > is equivalent to
    >
    > f = lambda *args: expr
    >
    > ?
    >
    > Steve
    > --
    > http://mail.python.org/mailman/listinfo/python-list
    >
    Michael DeHaan, Dec 17, 2004
    #7
  8. Steven Bethard wrote:

    > You're welcome to name the function whatever you want -- notice in my example that the function is
    > used in the statement:
    >
    > x = func or f
    >
    > If you'd prefer the statement to read:
    >
    > x = func or x
    >
    > that's also fine. Depends on what exactly 'x' is, and whether or not it really makes sense for
    > the function I called 'f' to have the same name as the variable called 'x'. It certainly may, but
    > since I wasn't giving real code, I didn't want to commit to that.


    if you write "def f", "f" is a variable, just like "x". "def" is an assignment
    statement.

    I'm not sure what "func" is supposed to be in your examples...

    > I assume that the point you were trying to make is that:
    >
    > def f(*args):
    > return expr
    >
    > is equivalent to
    >
    > f = lambda *args: expr
    >
    > ?


    >>> def f():

    .... return 1+2
    ....
    >>> g = lambda: 1 + 2
    >>> type(f)

    <type 'function'>
    >>> type(g)

    <type 'function'>

    >>> import dis
    >>> dis.dis(f)

    2 0 LOAD_CONST 1 (1)
    3 LOAD_CONST 2 (2)
    6 BINARY_ADD
    7 RETURN_VALUE
    >>> dis.dis(g)

    1 0 LOAD_CONST 1 (1)
    3 LOAD_CONST 2 (2)
    6 BINARY_ADD
    7 RETURN_VALUE

    >>> dir(f)

    ['__call__', '__class__', '__delattr__', '__dict__', '__doc__', '__get__', '__ge
    tattribute__', '__hash__', '__init__', '__module__', '__name__', '__new__', '__r
    educe__', '__reduce_ex__', '__repr__', '__setattr__', '__str__', 'func_closure',
    'func_code', 'func_defaults', 'func_dict', 'func_doc', 'func_globals', 'func_na
    me']
    >>> dir(g)

    ['__call__', '__class__', '__delattr__', '__dict__', '__doc__', '__get__', '__ge
    tattribute__', '__hash__', '__init__', '__module__', '__name__', '__new__', '__r
    educe__', '__reduce_ex__', '__repr__', '__setattr__', '__str__', 'func_closure',
    'func_code', 'func_defaults', 'func_dict', 'func_doc', 'func_globals', 'func_na
    me']

    >>> f.func_name

    'f'
    >>> g.func_name

    '<lambda>'

    </F>
    Fredrik Lundh, Dec 17, 2004
    #8
  9. Fredrik Lundh wrote:
    > I'm not sure what "func" is supposed to be in your examples...


    Just an extra variable used to make sure that the lambda was being used
    in a context (i.e. in an expression) where a simple def wouldn't
    suffice. If the example is confusing, consider the dict example
    instead. It makes it clearer that the lambdas are being used in places
    where an expression is required.

    Steve
    Steven Bethard, Dec 17, 2004
    #9
  10. Michael DeHaan wrote:
    > True enough, but suppose you want a hash of anonymous functions as
    > opposed to just a lexical?


    I've seen at least one reasonable example of this kind of thing:

    http://mail.python.org/pipermail/python-list/2004-October/245432.html

    Though I haven't yet seen an example that actually required lambdas with
    blocks...

    > Totally agreed about a small use here and there, but they do have some
    > use in dispatch tables, as they are a lot easier to read sometimes
    > than very long case statements. Of course, this would require
    > multi-line lambdas to exist...


    Certainly in the example above, I'd be willing to agree that the lambdas
    are at least as readable as a buch of def's above would have been. I'm
    not sure if multi-line lambdas would be as readable though... It all
    depends on what syntax you write them in -- you can see the struggle I
    went through in my other message... Where do I put the commas in a
    dict? Can't be at the end of the lambda or they turn the last
    expression into a tuple... I resorted to putting them on a separate
    line, but of course there are other solutions.


    If you have a good example of where you'd like to use multi-line
    lambdas, in, say, a dispatch table, I'd like to take a look at how you'd
    like to write them. I'm not yet convinced that there really is a
    readable way to write such things...

    Steve
    Steven Bethard, Dec 17, 2004
    #10
  11. Michael DeHaan wrote:

    > True enough, but suppose you want a hash of anonymous functions as
    > opposed to just a lexical? This is where lambas are nice to have.
    > Totally agreed about a small use here and there, but they do have some
    > use in dispatch tables, as they are a lot easier to read sometimes
    > than very long case statements.


    standard pattern:

    dispatch = {}

    def handle_a(...):
    ...
    dispatch["a"] = handle_a

    def handle_b(...):
    ...
    dispatch["b"] = handle_b

    def handle_c(...):
    ...
    dispatch["c"] = handle_c

    if you cannot think of a suitable name for a given case, you can
    name them all "case". for further encapsulation, you can put this
    in a class definition; dispatch will then become a dictionary con-
    taining unbound methods. if the case names all happen to be valid
    Python literals, you can get rid of the dispatch dictionary, and use
    getattr(self, "handle_" + case) to locate the right bound method (or
    if speed is important, use dir() to preload a dispatch dictionary with
    handlers). etc.

    </F>
    Fredrik Lundh, Dec 17, 2004
    #11
  12. Jason Zheng wrote:
    > The true beauty of lambda function is not the convenience of creating
    > functions without naming them. Lambda constructs truly enables
    > higher-order function. For example, I can create a function A that
    > returns a function B that does something interesting according to the
    > arguments that I pass to function A.


    Like this?

    def A(*args, **kwds):
    def B():
    print args, kwds
    return B

    But you don't need lambdas to do this. In fact, even in your email,
    you'll note that you referred to your two functions by name. If you're
    naming functions, why not use a def statement?

    Steve
    Steven Bethard, Dec 17, 2004
    #12
  13. Steven Bethard wrote:

    > I've seen at least one reasonable example of this kind of thing:
    >
    > http://mail.python.org/pipermail/python-list/2004-October/245432.html


    the code he's referring to doesn't seem to use that construct anymore, so
    it's not obvious what "dejavu.icontains" etc really is, but assuming they're
    strings, the following is a reasonable lambda-free alternative:

    class xforms:
    def icontains(self, x, y): return x + " Like '%" + y[1:-1] + "%'"
    def icontainedby(self, x, y):
    # icontainedby body goes here instead of in a separate function
    def istartswith(self, x, y): return x + " Like '" + y[1:-1] + "%'"
    def iendswith(self, x, y): return x + " Like '%" + y[1:-1] + "'"
    def ieq(self, x, y): return x + " = " + y
    def now(self): return "Now()"
    def today(self): return "DateValue(Now())",
    def year(self, x): return "Year(" + x + ")"
    def dispatch(self, tag, *args):
    return getattr(self, tag)(*args)

    here's another "reasonable example", btw:

    http://groups-beta.google.com/group/comp.lang.python/msg/11462b89a490a6ac

    this too could be rewritten to use a class (combined with re.sub and
    a callback, most likely).

    </F>
    Fredrik Lundh, Dec 17, 2004
    #13
  14. Jason Zheng wrote:

    > The true beauty of lambda function is not the convenience of creating
    > functions without naming them. Lambda constructs truly enables
    > higher-order function. For example, I can create a function A that
    > returns a function B that does something interesting according to the
    > arguments that I pass to function A.


    How does that differ from this?

    >>> def A(x):

    .... if x:
    .... def B(): return "True"
    .... else:
    .... def B(): return "False"
    .... return B
    ....
    >>> A(1)

    <function B at 0xa0c65dc>
    >>> _()

    'True'
    >>> A(0)

    <function B at 0xa0c65dc>
    >>> _()

    'False'
    --
    Michael Hoffman
    Michael Hoffman, Dec 17, 2004
    #14
  15. Fredrik Lundh wrote:
    > Steven Bethard wrote:
    >
    >>I've seen at least one reasonable example of this kind of thing:
    >>
    >>http://mail.python.org/pipermail/python-list/2004-October/245432.html

    >
    > the code he's referring to doesn't seem to use that construct anymore, so
    > it's not obvious what "dejavu.icontains" etc really is, but assuming they're
    > strings, the following is a reasonable lambda-free alternative:
    >
    > class xforms:
    > def icontains(self, x, y): return x + " Like '%" + y[1:-1] + "%'"
    > def icontainedby(self, x, y):
    > # icontainedby body goes here instead of in a separate function
    > def istartswith(self, x, y): return x + " Like '" + y[1:-1] + "%'"
    > def iendswith(self, x, y): return x + " Like '%" + y[1:-1] + "'"
    > def ieq(self, x, y): return x + " = " + y
    > def now(self): return "Now()"
    > def today(self): return "DateValue(Now())",
    > def year(self, x): return "Year(" + x + ")"
    > def dispatch(self, tag, *args):
    > return getattr(self, tag)(*args)


    This doesn't work if the strings aren't valid Python identifiers (e.g.
    "!CONTAINS!"). On the other hand, if they are (and you can be
    guaranteed that they will continue to be), then your solution above is
    nice, though if you want to fully reproduce the behavior, you probably
    also want the method

    def __getitem__(self, item):
    return getattr(self, item)

    Steve
    Steven Bethard, Dec 17, 2004
    #15
  16. Jason Zheng

    Terry Reedy Guest

    "Jason Zheng" <> wrote in message
    news:cpvhee$7uh$...
    > Steven Bethard wrote:
    >> Jason Zheng wrote:
    >>
    >>> I'm wondering why python still has limited lambda support. What's
    >>> stopping the developers of python to support more lisp-like lambda
    >>> function?


    They already have: given the fundamental syntax difference between all
    expressions and expressions within statements, def statements are at least
    the equivalent of lisp lambdas + name binding. When you get an exception
    traceback, a unique name is more helpful than the pseudoname <lambda>.
    Isolating the definition of a function in a separate statement also makes
    it possible to unittest the function.

    >> This comes up every few weeks on the list. If you haven't already,
    >> check the archives in Google for 'anonymous def' or 'anonymous
    >> function'. The usual response to this question is something along the
    >> lines of "if it's good enough to create a function for, it's good enough
    >> to name".


    What puzzles me is 1) why some people apparently think anonymity is good --
    is it really that hard to name non-trivial functions? and 2) why some
    people are so quick to recommend changes to Python before they understand
    what they can already do (wth def statements, in this case).

    > The true beauty of lambda function is not the convenience of creating
    > functions without naming them. Lambda constructs truly enables
    > higher-order function.


    And so do Python def statements coupled with Python design principles. In
    Python at least, the beauty of first-class functions has nothing to do with
    'lambda'.

    > For example, I can create a function A that returns a function B that
    > does something interesting according to the arguments that I pass to
    > function A.


    Golly gee. Pythoneers have done this with def for at least a decade, if
    not from the very beginning.

    Terry J. Reedy
    Terry Reedy, Dec 17, 2004
    #16
  17. Jason Zheng

    Jeff Shannon Guest

    Steven Bethard wrote:

    > Jason Zheng wrote:
    >
    >> The true beauty of lambda function is not the convenience of creating
    >> functions without naming them. Lambda constructs truly enables
    >> higher-order function. For example, I can create a function A that
    >> returns a function B that does something interesting according to the
    >> arguments that I pass to function A.

    >
    >
    > But you don't need lambdas to do this. In fact, even in your email,
    > you'll note that you referred to your two functions by name. If
    > you're naming functions, why not use a def statement?



    It occurs to me that, in a statically compiled language, function
    definitions all happen before the program starts, and thus that
    definition can't be affected by other variables (i.e. an outer
    function's parameters). In such statically compiled language, a lambda
    would be very useful simply because it's a *dynamic* function. Of
    course, in Python *all* functions are created dynamically, therefore
    (unlike most other languages) the majority of the benefits of lambdas
    already apply to standard Python functions.

    In the couple of years that I've been puzzling over why some people were
    so fixated upon lambdas as being essential, this hasn't occurred to me
    before. They really provide scant benefit in Python (which is why I was
    puzzled by the devotion to them), but they *do* provide a large benefit
    in other languages. It is, however, quite easy to miss that this
    relative weakness of Python lambdas is a direct consequence of the fact
    that a function def is an executable statement rather than a
    compilation-time declaration.

    Jeff Shannon
    Technician/Programmer
    Credit International
    Jeff Shannon, Dec 17, 2004
    #17
  18. Jeff Shannon wrote:
    > It occurs to me that, in a statically compiled language, function
    > definitions all happen before the program starts, and thus that
    > definition can't be affected by other variables (i.e. an outer
    > function's parameters).


    I think you might be confusing static compilation in a language with
    lack of first-class functions in a language. OCaml is compiled, but
    functions are first class objects, and nested scopes are accessible:

    # let f x =
    let g y =
    x + y
    in
    g;;
    val f : int -> int -> int = <fun>
    # f(1);;
    - : int -> int = <fun>
    # f(1)(2);;
    - : int = 3

    Note that the type of f is a function that takes an int and returns a
    function that takes an int and returns an int. OCaml handles nested
    scopes appropriately, and successfully compiles the function f (and
    infers the appropriate types). So the issue is not static compilation,
    but functions as first class objects.

    Of course, many statically compiled languages, e.g. C, C++, Java, do not
    provide functions as first class objects, so the confusion is not
    unnatural...

    Steve
    Steven Bethard, Dec 17, 2004
    #18
  19. Jason Zheng

    Jeff Shannon Guest

    Steven Bethard wrote:

    > Jeff Shannon wrote:
    >
    >> It occurs to me that, in a statically compiled language, function
    >> definitions all happen before the program starts, and thus that
    >> definition can't be affected by other variables (i.e. an outer
    >> function's parameters).

    >
    >
    > I think you might be confusing static compilation in a language with
    > lack of first-class functions in a language.



    Hm, possibly. I must confess that my direct knowledge is limited to a
    fairly narrow set of languages, and that C and C++ are the only
    statically-compiled languages I've used. Still, I'm not sure that it's
    just a matter of functions as first-class objects. Would OCaml (or some
    other static language) have something that's equivalent to this?

    def f(x):
    if x < 0:
    def g(y):
    return y * -1
    else:
    def g(y):
    return y
    return g

    foo = f(1)

    Here, nested scopes are not enough. Only one of these functions is
    created, and which one that is depends on the run-time value of the
    function parameter. A compiler couldn't know this ahead of time. I
    suppose it might be able to do something by compiling both of them,
    (though I'm not sure how it'd track two different functions with the
    same name in the same namespace...) but that seems a bit questionable to
    me...

    Jeff Shannon
    Technician/Programmer
    Credit International
    Jeff Shannon, Dec 18, 2004
    #19
  20. Jason Zheng

    Mike Meyer Guest

    Jeff Shannon <> writes:

    > Steven Bethard wrote:
    > Hm, possibly. I must confess that my direct knowledge is limited to a
    > fairly narrow set of languages, and that C and C++ are the only
    > statically-compiled languages I've used. Still, I'm not sure that
    > it's just a matter of functions as first-class objects. Would OCaml
    > (or some other static language) have something that's equivalent to
    > this?
    >
    > def f(x):
    > if x < 0:
    > def g(y):
    > return y * -1
    > else:
    > def g(y):
    > return y
    > return g
    >
    > foo = f(1)


    This is really no different than:

    def f(x):
    if x < 0:
    g = -y
    else:
    g = y
    return g

    The only difference is that you're binding the variable g to a y type
    instead of a function type. That's what "first class functions"
    means. You can treat functions like any other object, assign them to
    variables, pass them as parameters, and so on.

    <mike
    --
    Mike Meyer <> http://www.mired.org/home/mwm/
    Independent WWW/Perforce/FreeBSD/Unix consultant, email for more information.
    Mike Meyer, Dec 18, 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. Steven Knight
    Replies:
    0
    Views:
    1,154
    Steven Knight
    Aug 18, 2004
  2. Jp Calderone

    Re: better lambda support in the future?

    Jp Calderone, Dec 18, 2004, in forum: Python
    Replies:
    2
    Views:
    275
    Steve Holden
    Dec 18, 2004
  3. Roman Suzi
    Replies:
    13
    Views:
    582
    Bengt Richter
    Jan 7, 2005
  4. Steve Dogers

    lambda vs non-lambda proc

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

Share This Page