Enhance definition of functions

Yes, I know that multiline lambda will never be implemented in Python, but in many languages it is possible to write an anonymous function without using lambda at all. In JavaScript: Instead of "function <name>(<variables>){code}" you can write "var name; name=function(<variables>){code}" Python (proposed): def func(a,b): print(a+b) return a+b becomes func=function a,b: print(a+b) return a+b

What's wrong with the current syntax? Why can't you just write a def? I didn't do an exact count, but it looks like the lengths of the two function definitions differ by at most a single character. On Tue, Jul 30, 2013 at 11:19 AM, Musical Notation < musicdenotation@gmail.com> wrote:

On Tue, Jul 30, 2013 at 11:19 AM, Musical Notation <musicdenotation@gmail.com> wrote:
This seems like an odd misunderstanding to me. Of course Javascript has a lambda, it just happens to spell it 'f-u-n-c-t-i-o-n' rather than like 'l-a-m-b-d-a'. As with every other object, a lambda object can be assigned a name in Javascript... although it need not be, of course. You can also just use a Javascript lambda inline anywhere a code object makes sense, e.g.: higher_order_func(function(x,y){return x+y}, 2, 3); Of course, if you wanted to, you could have written: add2 = function(x,y){return x+y}; higher_order_func(add2, 2, 3); Or likewise: function add2(x,y){return x+y}; higher_order_func(add2, 2, 3); Other than not allowing full blocks in lambdas, Python is exactly the same. higher_order_func(lambda x,y: x+y, 2, 3) And as with Javascript, you *could* give the passed function a name with: add2 = lambda x,y: x+y Or with: def add2(x,y): return x+y It sounds like what you are asking for--after saying Python will never have it--is multi-line, full-block, lambdas in Python. For that, it has been discussed a lot of times, and no one has found a syntax that feel widely acceptable. -- Keeping medicines from the bloodstreams of the sick; food from the bellies of the hungry; books from the hands of the uneducated; technology from the underdeveloped; and putting advocates of freedom in prisons. Intellectual property is to the 21st century what the slave trade was to the 16th.

On 30 Jul, 2013, at 17:19, Musical Notation <musicdenotation@gmail.com> wrote:
Yes, I know that multiline lambda will never be implemented in Python, but in many languages it is possible to write an anonymous function without using lambda at all.
"Never" is a long time. AFAIK the main reason why Python doesn't have multi-line lambda's is that nobody has proposed a suitable syntax yet (and not for lack of trying, the archives of this list and python-dev contain a lot of proposals that were found lacking).
In JavaScript: Instead of "function <name>(<variables>){code}" you can write "var name; name=function(<variables>){code}"
That's just a lambda by another name.
This has a number a problems, as noted by Matthew this isn't shorter than the corresponding named function. It also introduces a new keyword, and because of that likely breaks existing code (especially because "function" is a fairly common word in IT). The syntax appears to indicate that the new construct is an expression, if so how would you use it in other contexts where expressions can be used(Such as function arguments, list literals, ...)? Ronald

On 7/30/2013 11:59 AM, Ronald Oussoren wrote:
There is also the fact that a generic .__name__ attribute of '<lambda>' is inferior to a possibly unique and meaningful name. This is not just in tracebacks. Consider [<built-in function sin>, <built-in function cos>] versus [<function <lambda> at 0x0000000003470B70>, <function <lambda> at 0x0000000003470BF8>] -- Terry Jan Reedy

On 31/07/13 11:41, Terry Reedy wrote:
True, but if we're going to hypothesize nice syntax for multi-line lambdas, it's not much harder to imagine that there's also nice syntax to give them a name and a doc string at the same time :-) I-don't-want-much-just-multi-line-lambda-and-ultimate-power-ly yr's, -- Steven (and I don't care that much about multi-line lambda)

On 7/31/2013 1:20 AM, Steven D'Aprano wrote:
But then they would not be anonymous. When I have a multiple line expression, I often pull out an anonymous expression and give it a local name to use within the expression to make the expression shorter and more comprehensible. So does most everyone else. So I have no desire to do the opposite with function definitions by sticking multiple line definition in the middle of an expression. I know Lisper do that, and the result is ofter difficult to impossible to read. In sort(key=?) calls, I use lambda for short, one-use key expressions, but I would never want to inject a multiple line expression into the middle. To me, it make the code less readable than separating a non-trivial key idea from the sort idea. -- Terry Jan Reedy

On 31 Jul, 2013, at 3:41, Terry Reedy <tjreedy@udel.edu> wrote:
It might be lack of imagination on my part, but I have a lot of nested functions named "function" or "callback" that are too complex to be a lambda, but too simple or specialized to bother making them proper functions. The key function for sort is one of the usecases. I'd love to have anonymous functions for that, but haven't seen a proposal for those yet that would fit the language. Ronald

I'd like multiline lambdas too, but the syntax is a thorny problem. F# is the only language I know (are there others?) that allows you to mix whitespace-delimited and paren-delimited expressions, e.g. with whitespace-blocks inside parens: let f n = n + ( if n % 2 = 0 then printf "lol" 1 else printf "omg" 2 ) f 0 // lol // 1 f 1 // omg // 3 f 2 // lol // 3 And it actually works as you'd expect, most of the time, so clearly doing such a thing is possible. On the other hand, even with lots of smart people behind F#, edge cases in the parsing of this sort of thing bites me pretty regularly. Although It'd be awesome if it could be implemented cleanly and predictably, I definitely do not want to be the one writing the grammar or parser to support this kind of syntax! -Haoyi On Wed, Jul 31, 2013 at 2:23 PM, Ronald Oussoren <ronaldoussoren@mac.com>wrote:

On 2013-07-31, at 08:37 , Haoyi Li wrote:
Haskell can do that: f n = n + ( case n `mod` 2 of 0 -> unsafePerformIO $ do putStrLn "lol" return 1 1 -> unsafePerformIO $ do putStrLn "omfg" return 2 ) although a difference is that it doesn't have statement blocks, only expressions (`do` blocks are sugar for monadic chain expressions)

On Jul 30, 2013, at 23:23, Ronald Oussoren <ronaldoussoren@mac.com> wrote:
Would it really help anything? If you're worried about keystrokes you can always call them "f" instead of "function". And I don't think anonymous functions would be as nice in tracebacks as even genetically-named ones. I think having to define them out of line is usually a more serious problem than having to name them, and if you solve that problem you may get the other one for free (although admittedly you may not, as the @in proposal shows...). Of course often, when I run into this, it's a matter of trying to write something that _could_ be an expression, without even needing a lambda... except that it would be a huge mess of partial and compose and other HOF calls and uses of operator functions and sometimes itertools stuff that would all be trivial in a different language but is horribly unpleasant in Python. And then I can compare the cost of having to write an out of line function in Python to the cost of writing the surrounding code in Haskell and I feel better. :)

On 31 July 2013 07:47, Andrew Barnert <abarnert@yahoo.com> wrote:
The only real reason I ever use lambdas (and would sometimes like a multiline version or similar) is for readability, where I want to pass a callback to a function and naming it and placing it before the call over-emphasises its importance. It's hard to make this objective, but to my eyes def k(obj): return obj['x'] / obj['y'] s = list(sorted(l, key=k) reads marginally worse than s = list(sorted(l, key=k)) where: def k(obj): return obj['x'] / obj['y'] simply because the focus of the block of code (building a sorted list) is at the start in the latter. But because the difference is so subtle, it's very hard to get a syntax that improves things sufficiently to justify new syntax. And it's also not at all obvious to me that any improvement in readability that can be gained in simple example code that you can post in an email, will actually still be present in "real world" code (which, in my experience, is always far messier than constructed examples :-)) Paul

From: Paul Moore <p.f.moore@gmail.com> Sent: Wednesday, July 31, 2013 2:15 AM
This is "the @in proposal" I referenced earlier—specifically, PEP 403 (http://www.python.org/dev/peps/pep-0403/). With PEP 403, your code would actually look like this: @in s = list(sorted(l, key=k)) def k(obj): return obj['x'] / obj['y'] Your syntax is closer to that of PEP 3150, but if you look toward the end of PEP 403, it specifically describes using PEP 3150-like syntax for the (simpler) PEP 403 semantics, and the result is exactly your suggestion except with the keyword "given" instead of "where".
But because the difference is so subtle, it's very hard to get a syntax that improves things sufficiently to justify new syntax. And it's also not at all obvious to me that any improvement in readability that can be gained in simple example code that you can post in an email, will actually still be present in "real world" code (which, in my experience, is always far messier than constructed examples :-))
The motivating examples in PEP 403 are, like yours, marginally better, for pretty much the same reason—putting the focus of the code at the start. And when PEP 403 pops up in relation to some different proposal, it's "if we had PEP 403, there would be less reason to want this new idea… but still not zero". And so on. It feels like there should be more benefit to the idea than this, but nobody's found it yet. And that's why it's stalled and deferred. If you can come up with a better motivating example, even if it's too hard to put into an email, that could definitely be helpful. But anyway, I think you're mostly agreeing with me. When neither lambda nor def feels right, it's usually not because you really want a multi-line expression, or a multi-line anonymous function, but because you want to get the petty details of the function "out of the way" of the important code, right?

On 1 August 2013 09:17, Andrew Barnert <abarnert@yahoo.com> wrote:
But anyway, I think you're mostly agreeing with me. When neither lambda nor def feels right, it's usually not because you really want a multi-line expression, or a multi-line anonymous function, but because you want to get the petty details of the function "out of the way" of the important code, right?
Yeah, I've been grappling with this problem for years, which is why I have two competing deferred PEPs about it :) For certain kinds of problem, the natural way to think about them is as "I want to do X", and as an incidental part of doing X, you need to define a function that does Y. Sorting, complex comprehensions, various flavours of event driven programming (especially GUI programming, where the yield-driven approach of PEP 3156 may not be appropriate, as well as the low level transport code for PEP 3156 style systems). Lambda isn't a great solution because it embeds all the complexity of the function directly in the main expression, obscuring the fact that the overall operation is "do X". Ruby's block syntax is an elegant solution, but the specific problem with adapting that to Python is deciding how to spell the forward reference to the trailing definition. Ruby solves that problem through a convention (the block is just the last positional argument), but Python has no such convention - there's a wide variety of signatures for higher order operations, and a syntax that required new signatures for everything is no solution at all. PEP 403 is the approach I dislike least so far, but that's a far cry from being something I'm willing to propose for inclusion in the language. The "@in" does hint at the out of order execution nicely, but it's also a bit too heavy (drawing attention away from the subsequent simple statement), and as an ordinary name, the forward reference doesn't quite stand out enough. PEP 3150 could possibly by improved by having the hidden function implicitly end with (a more efficient equivalent of) "return types.SimpleNamespace(**locals())" and introducing "?" as a forward reference to that result: sorted_data = sorted(data, key=?.k) given: def k(item): return item.attr1, item.attr2 But it's hardly what one could call a *concise* syntax. On the other hand, it *does* let you do some pretty neat things, like: dispatch_table = vars(?) given: def command1(*args, **kwds): ... def command2(*args, **kwds): ... def command3(*args, **kwds): ... I would also tweak the early binding syntax to require an additional keyword to make it read more like English: seq = [] for i in range(10): seq.append(?.f) given i=i in: def f(): return i assert [f() for f in seq] == list(range(10)) Using up another precious symbol would be a big call, but it's starting to feel more like something of sufficient power to justify new syntax. Cheers, Nick. -- Nick Coghlan | ncoghlan@gmail.com | Brisbane, Australia

Le Fri, 2 Aug 2013 22:48:33 +1000, Nick Coghlan <ncoghlan@gmail.com> a écrit :
I think any "inline function" proposal should focus on callback-based programming for its use cases. In this context, you usually have one or two callbacks (two in Twisted-style programming: one for success, one for failure), passed positionally to a consuming function: loop.create_connection((host, port), @cb, @eb) where: def cb(sock): # Do something with socket def eb(exc): logging.exception( "Failed connecting to %s:%s", host, port) Regards Antoine.

On 2 August 2013 23:55, Antoine Pitrou <solipsis@pitrou.net> wrote:
I think callback based programming is a *good* use case, certainly, but not the only one.
We can't use 'where' because we know it conflicts with the SQL sense of the term in too many APIs. We're reasonably sure we can get away with "given" without too much conflict, though. Using "@" as the marker character is also problematic, since the following degenerate case will probably confuse the parser (due to it looking too much like a decorator clause): @something() given: ... I liked the notion of "?" as suggesting doubt and uncertainty - an element of "leave this undefined for now, we'll fill it in later". While the out of order execution is related to decorators (hence @in for PEP 403), I think PEP 3150 is more of a different notion, especially with the revisions I suggested in this thread. I believe your example still looks reasonable with the "?." notation for the forward reference: loop.create_connection((host, port), ?.cb, ?.eb) given: def cb(sock): # Do something with socket def eb(exc): logging.exception( "Failed connecting to %s:%s", host, port) Anyway, not something that's going to happen for 3.4, but a problem I'm happy to keep chipping away at - some day we might find a proposed solution that doesn't send Guido screaming in the other direction :) Cheers, Nick. -- Nick Coghlan | ncoghlan@gmail.com | Brisbane, Australia

Le Sat, 3 Aug 2013 01:46:37 +1000, Nick Coghlan <ncoghlan@gmail.com> a écrit :
How about reusing "with"? There's no ambiguity with context managers since the syntactic context is different.
No, that would simply be forbidden. In this proposal, "@" can only mark names of parameters in function calls. We already reuse "*" and "**" for a specific meaning in front of function call parameters, so there's a precedent for such polysemy.
I liked the notion of "?" as suggesting doubt and uncertainty - an element of "leave this undefined for now, we'll fill it in later".
I don't really like it :-) "?" has other meanings traditionally: as part of the ternary operator in C-like languages (many of them), as a wildcard character in pattern matching languages, as a marker of optional matchers in regular expressions. Also, I really don't like the idea that "?" represents a full-blown object with attribute access capabilities and whatnot. It smells too much like Perl-style (Ruby-style?) magic variables. My proposal is more limited: it's a syntactic addition, but it doesn't create new runtime objects or types. Regards Antoine.

On Aug 2, 2013, at 9:00, Antoine Pitrou <solipsis@pitrou.net> wrote:
That's fine if callbacks are the _only_ case you want to handle, but as Nick just explained, there are many other cases that are also useful. The middle of an if expression in a comprehension, for example, isn't a function parameter. Also, when you have a long function call expression--as you almost always do in, say, PyObjC or PyWin32 GUIs--you often want to put each parameter on its own line. While that won't confuse the parser, it could easily confuse a human, who will see "@callback," on a line by itself and think "decorator". It's probably worth taking some real examples from a bunch of different domains where you've defined something out-of-line but would use this proposal if you could, and rewriting them with each variation to see what they look like.

On 3 August 2013 02:41, Michael Walter <michael.walter@gmail.com> wrote:
It's more than just the parser that needs that extra help to make it implementable :) However, the syntactic marker is helpful for human readers, too - it makes it clear which names come from the statement local namespace, and which are just ordinary name references. Cheers, Nick. -- Nick Coghlan | ncoghlan@gmail.com | Brisbane, Australia

On Fri, 2 Aug 2013 09:25:05 -0700 Andrew Barnert <abarnert@yahoo.com> wrote:
There may be many other cases, but almost any time people complain about the lack of inline functions, it's in situations where they are declaring callbacks (i.e. GUI- or network-programming). So, yes, I don't think the other use cases should be a primary point of concern.
Even if indented, inside a parenthesis and not preceding a similarly indented "def"? Regards Antoine.

PEP 3150 is actually pretty simple to implement using macros:
The macro is about 5 lines long, since it's exactly the same as my 15-line quick lambda macro (i.e. f[_ + _] -> lambda a, b: a + b); this should have worked out of the box, requiring no additional code: @f[map(_, [1, 2, 3]] def thing(x): return x + 1 But it doesn't due to the parser not liking [] in decorators; boo for arbitrary syntactic restrictions =( =( =(. This only works for higher-order-functions with a single callback. As things stand now, the status-quo solution for multi-callback functions is to make a class and inherit from it, and fill in the methods you need to fill in. There wasn't any PEP for this but that's what people are doing all over the place: many many classes exist purely to let people fill in the missing functions. Not because the class objects have any state, or you ever intend to create objects which will live for more than one function call: class MyClass(BaseRequestClass): def print_data(d): print d def print_error(failure): sys.sys.stderr.write(str(failure)) result = MyClass().make_request() # never gonna use MyClass() ever again! Java uses this pattern too, and I do not like it. One possibility, though, would just codify/streamline the status quo, via macros: @in(make_request(_, _)) class result: def print_data(d): print d def print_error(failure): sys.sys.stderr.write(str(failure)) Which would desugar (using macro-magic and metaclasses) into def print_data(d): print d def print_error(failure): sys.sys.stderr.write(str(failure)) result = make_request(print_data, print_error) Potential bikesheds are over whether to use `_` to leave holes, or `print_data` and `print_error` as named arguments, as well as whether `result` should be a class or function def. Overall, though, it looks exactly like PEP3150 except this public_name = ?.MeaningfulClassName(*params) given: class MeaningfulClassName(): ... becomes this: @in(_.MeaningfulClassName(*params)) class public_name: class MeaningfulClassName(): ... Which is pretty close. I can put up the implementations of all of these things if anyone's interested in playing around with the syntax/semantics in the REPL. -Haoyi On Sat, Aug 3, 2013 at 1:46 AM, Antoine Pitrou <solipsis@pitrou.net> wrote:

It does feel like Perl, but, what if there was a keyword after the symbol? It'd be more readable and not Perl-ish, but, it wouldn't confuse the parser(or at least I wouldn't think it would). Antoine Pitrou <solipsis@pitrou.net> wrote:
-- Sent from my Android phone with K-9 Mail. Please excuse my brevity.

On 08/02/2013 07:48 AM, Nick Coghlan wrote:
I'm not sure how much a function adds to complexity. Generally they simplify things by moving the complexity to within the function. But short one off functions are a different thing. In most cases they are in the following situations: 1. Reuse a small bock of code over and over again locally. 2. Capture a value now, to be used later with that code block later. 3. Be sent into or out of a context so it can be used with values that can't be accessed locally or presently.
My feelings is that this type of thing requires a lower level solution, rather than a higher level abstraction. All of the above cases could be handled nicely if we could define a code block without a signature and call it with separately defined dictionary. It might look something like... seq = [] for i in range(10): ns = dict(i=i) co = def: i seq.append(ns with co) assert [expr() for expr in seq] == list(range(10)) It could be shortened to... seq = [({'i':i} with def:i) for i in range(10)] assert [expr() for expr in seq] == list(range(10)) The 'def:..' expression could return a code object. Which by itself wouldn't be callable. To make it callable, you would need to combine it with a signature object, or a name space. (Some sanity checks could be made at that time.) A signature object would return a name space constructor. This part is the part we don't need in many cases. (*) So being able to use an already constructed dictionary (or a yet to be constructed dictionary) as a name space has some advantages. The 'with' keyword is used here to combine two objects together. At least one of them would need to know what to do with the other. In this case it's the dictionary object that knows how to take a code object and return a callable frame like object. Probably it has a __with_code__ method. It may be too general of a definition of 'with', but possibly that can also be a good thing. If it always results in a callable object, then it would have just enough consistency to be easy to figure out when you come across them later without being too restrictive. But this part is just an option as a dictionary could just have a method.. callable_frame = {'i':i}.callable_with(def: i) Cheers, Ron

How about something like: f = indef(x, y): print x, y It's essentially storing lambdas. The syntax was taken from http://blog.deliciousrobots.com/2010/3/24/a-simple-compiler-with-python-and-.... indef stands for 'inline definition'. I've never heard someone use that name before. Or you could do 'slambda' for 'stored lambda'. Musical Notation <musicdenotation@gmail.com> wrote:
-- Sent from my Android phone with K-9 Mail. Please excuse my brevity.

On 07/30/2013 05:22 PM, Nick Coghlan wrote:
Or the old "let" statement. While writing a little bytecode interpreter in python, (To try some ideas out.), I found out it's much easier to parse source code if a line starts with a statement keyword such as 'let' or 'def'. And I suspect is why early languages followed that pattern. Cheers, Ron

On Jul 30, 2013, at 11:30, Ryan <rymg19@gmail.com> wrote:
You can already store lambdas. Or, more precisely, you can store functions. A lambda isn't a type; it's just a different way of creating functions, exactly the same type of functions you get from the def statement. And functions are first class values that can be bound to a name just like any other value. Meanwhile, the only advantages of lambda over def are that you don't have to come up with a name, and you can use it in an expression. So, trying to come up with a statement for giving lambdas names implies that there's something fundamental you're missing that would make your life a lot easier. Maybe you didn't know you could use def locally? Or you're trying to build code out of eval-ing strings because you don't know about closures? Or... Well, there are lots of possibilities. If you explain what you want to do that you think your new syntax would help with, I'm 99% sure Python already has a better way to do it.

I believe that anything that can not be expressed as a Python anonymous function must be a def. It is possible to express conditionals and loops within a lambda statement, if that is what you are looking for:
BTW, if a multi-statement anonymous function syntax was to be considered seriously, I'd recommend a lambda statement with colon replaced with a brace-delimited block, which would barely cause code written for an interpreter lacking it get refused: server = nodeishServer( lambda req, res { res.writeHead(200, ContentType= "text/html"); res.end("Hello"); } ) In fact, grammar for every statement which introduces a new block (if, def, for, with, lambda) can be altered such that if the statement ends with a `:' (semicolon), following lines are parsed as in usual Python syntax, or, if the statement ends with a `{' (left brace), following lines are parsed with non-indentation defined, C-ish syntax. So: def fibonacci(n): x, y, z = 1, 1, 0 for i in range(1, n): z = x x += y y = x return x could be also written as def fibonacci(n) { x, y, z = 1, 1, 0; for i in range(1, n) { z = x; x += y; y = x; } return x; } which is a) subject of a different thread, and b) ridiculous. -gk On 30 July 2013 18:19, Musical Notation <musicdenotation@gmail.com> wrote:

What's wrong with the current syntax? Why can't you just write a def? I didn't do an exact count, but it looks like the lengths of the two function definitions differ by at most a single character. On Tue, Jul 30, 2013 at 11:19 AM, Musical Notation < musicdenotation@gmail.com> wrote:

On Tue, Jul 30, 2013 at 11:19 AM, Musical Notation <musicdenotation@gmail.com> wrote:
This seems like an odd misunderstanding to me. Of course Javascript has a lambda, it just happens to spell it 'f-u-n-c-t-i-o-n' rather than like 'l-a-m-b-d-a'. As with every other object, a lambda object can be assigned a name in Javascript... although it need not be, of course. You can also just use a Javascript lambda inline anywhere a code object makes sense, e.g.: higher_order_func(function(x,y){return x+y}, 2, 3); Of course, if you wanted to, you could have written: add2 = function(x,y){return x+y}; higher_order_func(add2, 2, 3); Or likewise: function add2(x,y){return x+y}; higher_order_func(add2, 2, 3); Other than not allowing full blocks in lambdas, Python is exactly the same. higher_order_func(lambda x,y: x+y, 2, 3) And as with Javascript, you *could* give the passed function a name with: add2 = lambda x,y: x+y Or with: def add2(x,y): return x+y It sounds like what you are asking for--after saying Python will never have it--is multi-line, full-block, lambdas in Python. For that, it has been discussed a lot of times, and no one has found a syntax that feel widely acceptable. -- Keeping medicines from the bloodstreams of the sick; food from the bellies of the hungry; books from the hands of the uneducated; technology from the underdeveloped; and putting advocates of freedom in prisons. Intellectual property is to the 21st century what the slave trade was to the 16th.

On 30 Jul, 2013, at 17:19, Musical Notation <musicdenotation@gmail.com> wrote:
Yes, I know that multiline lambda will never be implemented in Python, but in many languages it is possible to write an anonymous function without using lambda at all.
"Never" is a long time. AFAIK the main reason why Python doesn't have multi-line lambda's is that nobody has proposed a suitable syntax yet (and not for lack of trying, the archives of this list and python-dev contain a lot of proposals that were found lacking).
In JavaScript: Instead of "function <name>(<variables>){code}" you can write "var name; name=function(<variables>){code}"
That's just a lambda by another name.
This has a number a problems, as noted by Matthew this isn't shorter than the corresponding named function. It also introduces a new keyword, and because of that likely breaks existing code (especially because "function" is a fairly common word in IT). The syntax appears to indicate that the new construct is an expression, if so how would you use it in other contexts where expressions can be used(Such as function arguments, list literals, ...)? Ronald

On 7/30/2013 11:59 AM, Ronald Oussoren wrote:
There is also the fact that a generic .__name__ attribute of '<lambda>' is inferior to a possibly unique and meaningful name. This is not just in tracebacks. Consider [<built-in function sin>, <built-in function cos>] versus [<function <lambda> at 0x0000000003470B70>, <function <lambda> at 0x0000000003470BF8>] -- Terry Jan Reedy

On 31/07/13 11:41, Terry Reedy wrote:
True, but if we're going to hypothesize nice syntax for multi-line lambdas, it's not much harder to imagine that there's also nice syntax to give them a name and a doc string at the same time :-) I-don't-want-much-just-multi-line-lambda-and-ultimate-power-ly yr's, -- Steven (and I don't care that much about multi-line lambda)

On 7/31/2013 1:20 AM, Steven D'Aprano wrote:
But then they would not be anonymous. When I have a multiple line expression, I often pull out an anonymous expression and give it a local name to use within the expression to make the expression shorter and more comprehensible. So does most everyone else. So I have no desire to do the opposite with function definitions by sticking multiple line definition in the middle of an expression. I know Lisper do that, and the result is ofter difficult to impossible to read. In sort(key=?) calls, I use lambda for short, one-use key expressions, but I would never want to inject a multiple line expression into the middle. To me, it make the code less readable than separating a non-trivial key idea from the sort idea. -- Terry Jan Reedy

On 31 Jul, 2013, at 3:41, Terry Reedy <tjreedy@udel.edu> wrote:
It might be lack of imagination on my part, but I have a lot of nested functions named "function" or "callback" that are too complex to be a lambda, but too simple or specialized to bother making them proper functions. The key function for sort is one of the usecases. I'd love to have anonymous functions for that, but haven't seen a proposal for those yet that would fit the language. Ronald

I'd like multiline lambdas too, but the syntax is a thorny problem. F# is the only language I know (are there others?) that allows you to mix whitespace-delimited and paren-delimited expressions, e.g. with whitespace-blocks inside parens: let f n = n + ( if n % 2 = 0 then printf "lol" 1 else printf "omg" 2 ) f 0 // lol // 1 f 1 // omg // 3 f 2 // lol // 3 And it actually works as you'd expect, most of the time, so clearly doing such a thing is possible. On the other hand, even with lots of smart people behind F#, edge cases in the parsing of this sort of thing bites me pretty regularly. Although It'd be awesome if it could be implemented cleanly and predictably, I definitely do not want to be the one writing the grammar or parser to support this kind of syntax! -Haoyi On Wed, Jul 31, 2013 at 2:23 PM, Ronald Oussoren <ronaldoussoren@mac.com>wrote:

On 2013-07-31, at 08:37 , Haoyi Li wrote:
Haskell can do that: f n = n + ( case n `mod` 2 of 0 -> unsafePerformIO $ do putStrLn "lol" return 1 1 -> unsafePerformIO $ do putStrLn "omfg" return 2 ) although a difference is that it doesn't have statement blocks, only expressions (`do` blocks are sugar for monadic chain expressions)

On Jul 30, 2013, at 23:23, Ronald Oussoren <ronaldoussoren@mac.com> wrote:
Would it really help anything? If you're worried about keystrokes you can always call them "f" instead of "function". And I don't think anonymous functions would be as nice in tracebacks as even genetically-named ones. I think having to define them out of line is usually a more serious problem than having to name them, and if you solve that problem you may get the other one for free (although admittedly you may not, as the @in proposal shows...). Of course often, when I run into this, it's a matter of trying to write something that _could_ be an expression, without even needing a lambda... except that it would be a huge mess of partial and compose and other HOF calls and uses of operator functions and sometimes itertools stuff that would all be trivial in a different language but is horribly unpleasant in Python. And then I can compare the cost of having to write an out of line function in Python to the cost of writing the surrounding code in Haskell and I feel better. :)

On 31 July 2013 07:47, Andrew Barnert <abarnert@yahoo.com> wrote:
The only real reason I ever use lambdas (and would sometimes like a multiline version or similar) is for readability, where I want to pass a callback to a function and naming it and placing it before the call over-emphasises its importance. It's hard to make this objective, but to my eyes def k(obj): return obj['x'] / obj['y'] s = list(sorted(l, key=k) reads marginally worse than s = list(sorted(l, key=k)) where: def k(obj): return obj['x'] / obj['y'] simply because the focus of the block of code (building a sorted list) is at the start in the latter. But because the difference is so subtle, it's very hard to get a syntax that improves things sufficiently to justify new syntax. And it's also not at all obvious to me that any improvement in readability that can be gained in simple example code that you can post in an email, will actually still be present in "real world" code (which, in my experience, is always far messier than constructed examples :-)) Paul

From: Paul Moore <p.f.moore@gmail.com> Sent: Wednesday, July 31, 2013 2:15 AM
This is "the @in proposal" I referenced earlier—specifically, PEP 403 (http://www.python.org/dev/peps/pep-0403/). With PEP 403, your code would actually look like this: @in s = list(sorted(l, key=k)) def k(obj): return obj['x'] / obj['y'] Your syntax is closer to that of PEP 3150, but if you look toward the end of PEP 403, it specifically describes using PEP 3150-like syntax for the (simpler) PEP 403 semantics, and the result is exactly your suggestion except with the keyword "given" instead of "where".
But because the difference is so subtle, it's very hard to get a syntax that improves things sufficiently to justify new syntax. And it's also not at all obvious to me that any improvement in readability that can be gained in simple example code that you can post in an email, will actually still be present in "real world" code (which, in my experience, is always far messier than constructed examples :-))
The motivating examples in PEP 403 are, like yours, marginally better, for pretty much the same reason—putting the focus of the code at the start. And when PEP 403 pops up in relation to some different proposal, it's "if we had PEP 403, there would be less reason to want this new idea… but still not zero". And so on. It feels like there should be more benefit to the idea than this, but nobody's found it yet. And that's why it's stalled and deferred. If you can come up with a better motivating example, even if it's too hard to put into an email, that could definitely be helpful. But anyway, I think you're mostly agreeing with me. When neither lambda nor def feels right, it's usually not because you really want a multi-line expression, or a multi-line anonymous function, but because you want to get the petty details of the function "out of the way" of the important code, right?

On 1 August 2013 09:17, Andrew Barnert <abarnert@yahoo.com> wrote:
But anyway, I think you're mostly agreeing with me. When neither lambda nor def feels right, it's usually not because you really want a multi-line expression, or a multi-line anonymous function, but because you want to get the petty details of the function "out of the way" of the important code, right?
Yeah, I've been grappling with this problem for years, which is why I have two competing deferred PEPs about it :) For certain kinds of problem, the natural way to think about them is as "I want to do X", and as an incidental part of doing X, you need to define a function that does Y. Sorting, complex comprehensions, various flavours of event driven programming (especially GUI programming, where the yield-driven approach of PEP 3156 may not be appropriate, as well as the low level transport code for PEP 3156 style systems). Lambda isn't a great solution because it embeds all the complexity of the function directly in the main expression, obscuring the fact that the overall operation is "do X". Ruby's block syntax is an elegant solution, but the specific problem with adapting that to Python is deciding how to spell the forward reference to the trailing definition. Ruby solves that problem through a convention (the block is just the last positional argument), but Python has no such convention - there's a wide variety of signatures for higher order operations, and a syntax that required new signatures for everything is no solution at all. PEP 403 is the approach I dislike least so far, but that's a far cry from being something I'm willing to propose for inclusion in the language. The "@in" does hint at the out of order execution nicely, but it's also a bit too heavy (drawing attention away from the subsequent simple statement), and as an ordinary name, the forward reference doesn't quite stand out enough. PEP 3150 could possibly by improved by having the hidden function implicitly end with (a more efficient equivalent of) "return types.SimpleNamespace(**locals())" and introducing "?" as a forward reference to that result: sorted_data = sorted(data, key=?.k) given: def k(item): return item.attr1, item.attr2 But it's hardly what one could call a *concise* syntax. On the other hand, it *does* let you do some pretty neat things, like: dispatch_table = vars(?) given: def command1(*args, **kwds): ... def command2(*args, **kwds): ... def command3(*args, **kwds): ... I would also tweak the early binding syntax to require an additional keyword to make it read more like English: seq = [] for i in range(10): seq.append(?.f) given i=i in: def f(): return i assert [f() for f in seq] == list(range(10)) Using up another precious symbol would be a big call, but it's starting to feel more like something of sufficient power to justify new syntax. Cheers, Nick. -- Nick Coghlan | ncoghlan@gmail.com | Brisbane, Australia

Le Fri, 2 Aug 2013 22:48:33 +1000, Nick Coghlan <ncoghlan@gmail.com> a écrit :
I think any "inline function" proposal should focus on callback-based programming for its use cases. In this context, you usually have one or two callbacks (two in Twisted-style programming: one for success, one for failure), passed positionally to a consuming function: loop.create_connection((host, port), @cb, @eb) where: def cb(sock): # Do something with socket def eb(exc): logging.exception( "Failed connecting to %s:%s", host, port) Regards Antoine.

On 2 August 2013 23:55, Antoine Pitrou <solipsis@pitrou.net> wrote:
I think callback based programming is a *good* use case, certainly, but not the only one.
We can't use 'where' because we know it conflicts with the SQL sense of the term in too many APIs. We're reasonably sure we can get away with "given" without too much conflict, though. Using "@" as the marker character is also problematic, since the following degenerate case will probably confuse the parser (due to it looking too much like a decorator clause): @something() given: ... I liked the notion of "?" as suggesting doubt and uncertainty - an element of "leave this undefined for now, we'll fill it in later". While the out of order execution is related to decorators (hence @in for PEP 403), I think PEP 3150 is more of a different notion, especially with the revisions I suggested in this thread. I believe your example still looks reasonable with the "?." notation for the forward reference: loop.create_connection((host, port), ?.cb, ?.eb) given: def cb(sock): # Do something with socket def eb(exc): logging.exception( "Failed connecting to %s:%s", host, port) Anyway, not something that's going to happen for 3.4, but a problem I'm happy to keep chipping away at - some day we might find a proposed solution that doesn't send Guido screaming in the other direction :) Cheers, Nick. -- Nick Coghlan | ncoghlan@gmail.com | Brisbane, Australia

Le Sat, 3 Aug 2013 01:46:37 +1000, Nick Coghlan <ncoghlan@gmail.com> a écrit :
How about reusing "with"? There's no ambiguity with context managers since the syntactic context is different.
No, that would simply be forbidden. In this proposal, "@" can only mark names of parameters in function calls. We already reuse "*" and "**" for a specific meaning in front of function call parameters, so there's a precedent for such polysemy.
I liked the notion of "?" as suggesting doubt and uncertainty - an element of "leave this undefined for now, we'll fill it in later".
I don't really like it :-) "?" has other meanings traditionally: as part of the ternary operator in C-like languages (many of them), as a wildcard character in pattern matching languages, as a marker of optional matchers in regular expressions. Also, I really don't like the idea that "?" represents a full-blown object with attribute access capabilities and whatnot. It smells too much like Perl-style (Ruby-style?) magic variables. My proposal is more limited: it's a syntactic addition, but it doesn't create new runtime objects or types. Regards Antoine.

On Aug 2, 2013, at 9:00, Antoine Pitrou <solipsis@pitrou.net> wrote:
That's fine if callbacks are the _only_ case you want to handle, but as Nick just explained, there are many other cases that are also useful. The middle of an if expression in a comprehension, for example, isn't a function parameter. Also, when you have a long function call expression--as you almost always do in, say, PyObjC or PyWin32 GUIs--you often want to put each parameter on its own line. While that won't confuse the parser, it could easily confuse a human, who will see "@callback," on a line by itself and think "decorator". It's probably worth taking some real examples from a bunch of different domains where you've defined something out-of-line but would use this proposal if you could, and rewriting them with each variation to see what they look like.

On 3 August 2013 02:41, Michael Walter <michael.walter@gmail.com> wrote:
It's more than just the parser that needs that extra help to make it implementable :) However, the syntactic marker is helpful for human readers, too - it makes it clear which names come from the statement local namespace, and which are just ordinary name references. Cheers, Nick. -- Nick Coghlan | ncoghlan@gmail.com | Brisbane, Australia

On Fri, 2 Aug 2013 09:25:05 -0700 Andrew Barnert <abarnert@yahoo.com> wrote:
There may be many other cases, but almost any time people complain about the lack of inline functions, it's in situations where they are declaring callbacks (i.e. GUI- or network-programming). So, yes, I don't think the other use cases should be a primary point of concern.
Even if indented, inside a parenthesis and not preceding a similarly indented "def"? Regards Antoine.

PEP 3150 is actually pretty simple to implement using macros:
The macro is about 5 lines long, since it's exactly the same as my 15-line quick lambda macro (i.e. f[_ + _] -> lambda a, b: a + b); this should have worked out of the box, requiring no additional code: @f[map(_, [1, 2, 3]] def thing(x): return x + 1 But it doesn't due to the parser not liking [] in decorators; boo for arbitrary syntactic restrictions =( =( =(. This only works for higher-order-functions with a single callback. As things stand now, the status-quo solution for multi-callback functions is to make a class and inherit from it, and fill in the methods you need to fill in. There wasn't any PEP for this but that's what people are doing all over the place: many many classes exist purely to let people fill in the missing functions. Not because the class objects have any state, or you ever intend to create objects which will live for more than one function call: class MyClass(BaseRequestClass): def print_data(d): print d def print_error(failure): sys.sys.stderr.write(str(failure)) result = MyClass().make_request() # never gonna use MyClass() ever again! Java uses this pattern too, and I do not like it. One possibility, though, would just codify/streamline the status quo, via macros: @in(make_request(_, _)) class result: def print_data(d): print d def print_error(failure): sys.sys.stderr.write(str(failure)) Which would desugar (using macro-magic and metaclasses) into def print_data(d): print d def print_error(failure): sys.sys.stderr.write(str(failure)) result = make_request(print_data, print_error) Potential bikesheds are over whether to use `_` to leave holes, or `print_data` and `print_error` as named arguments, as well as whether `result` should be a class or function def. Overall, though, it looks exactly like PEP3150 except this public_name = ?.MeaningfulClassName(*params) given: class MeaningfulClassName(): ... becomes this: @in(_.MeaningfulClassName(*params)) class public_name: class MeaningfulClassName(): ... Which is pretty close. I can put up the implementations of all of these things if anyone's interested in playing around with the syntax/semantics in the REPL. -Haoyi On Sat, Aug 3, 2013 at 1:46 AM, Antoine Pitrou <solipsis@pitrou.net> wrote:

It does feel like Perl, but, what if there was a keyword after the symbol? It'd be more readable and not Perl-ish, but, it wouldn't confuse the parser(or at least I wouldn't think it would). Antoine Pitrou <solipsis@pitrou.net> wrote:
-- Sent from my Android phone with K-9 Mail. Please excuse my brevity.

On 08/02/2013 07:48 AM, Nick Coghlan wrote:
I'm not sure how much a function adds to complexity. Generally they simplify things by moving the complexity to within the function. But short one off functions are a different thing. In most cases they are in the following situations: 1. Reuse a small bock of code over and over again locally. 2. Capture a value now, to be used later with that code block later. 3. Be sent into or out of a context so it can be used with values that can't be accessed locally or presently.
My feelings is that this type of thing requires a lower level solution, rather than a higher level abstraction. All of the above cases could be handled nicely if we could define a code block without a signature and call it with separately defined dictionary. It might look something like... seq = [] for i in range(10): ns = dict(i=i) co = def: i seq.append(ns with co) assert [expr() for expr in seq] == list(range(10)) It could be shortened to... seq = [({'i':i} with def:i) for i in range(10)] assert [expr() for expr in seq] == list(range(10)) The 'def:..' expression could return a code object. Which by itself wouldn't be callable. To make it callable, you would need to combine it with a signature object, or a name space. (Some sanity checks could be made at that time.) A signature object would return a name space constructor. This part is the part we don't need in many cases. (*) So being able to use an already constructed dictionary (or a yet to be constructed dictionary) as a name space has some advantages. The 'with' keyword is used here to combine two objects together. At least one of them would need to know what to do with the other. In this case it's the dictionary object that knows how to take a code object and return a callable frame like object. Probably it has a __with_code__ method. It may be too general of a definition of 'with', but possibly that can also be a good thing. If it always results in a callable object, then it would have just enough consistency to be easy to figure out when you come across them later without being too restrictive. But this part is just an option as a dictionary could just have a method.. callable_frame = {'i':i}.callable_with(def: i) Cheers, Ron

How about something like: f = indef(x, y): print x, y It's essentially storing lambdas. The syntax was taken from http://blog.deliciousrobots.com/2010/3/24/a-simple-compiler-with-python-and-.... indef stands for 'inline definition'. I've never heard someone use that name before. Or you could do 'slambda' for 'stored lambda'. Musical Notation <musicdenotation@gmail.com> wrote:
-- Sent from my Android phone with K-9 Mail. Please excuse my brevity.

On 07/30/2013 05:22 PM, Nick Coghlan wrote:
Or the old "let" statement. While writing a little bytecode interpreter in python, (To try some ideas out.), I found out it's much easier to parse source code if a line starts with a statement keyword such as 'let' or 'def'. And I suspect is why early languages followed that pattern. Cheers, Ron

On Jul 30, 2013, at 11:30, Ryan <rymg19@gmail.com> wrote:
You can already store lambdas. Or, more precisely, you can store functions. A lambda isn't a type; it's just a different way of creating functions, exactly the same type of functions you get from the def statement. And functions are first class values that can be bound to a name just like any other value. Meanwhile, the only advantages of lambda over def are that you don't have to come up with a name, and you can use it in an expression. So, trying to come up with a statement for giving lambdas names implies that there's something fundamental you're missing that would make your life a lot easier. Maybe you didn't know you could use def locally? Or you're trying to build code out of eval-ing strings because you don't know about closures? Or... Well, there are lots of possibilities. If you explain what you want to do that you think your new syntax would help with, I'm 99% sure Python already has a better way to do it.

I believe that anything that can not be expressed as a Python anonymous function must be a def. It is possible to express conditionals and loops within a lambda statement, if that is what you are looking for:
BTW, if a multi-statement anonymous function syntax was to be considered seriously, I'd recommend a lambda statement with colon replaced with a brace-delimited block, which would barely cause code written for an interpreter lacking it get refused: server = nodeishServer( lambda req, res { res.writeHead(200, ContentType= "text/html"); res.end("Hello"); } ) In fact, grammar for every statement which introduces a new block (if, def, for, with, lambda) can be altered such that if the statement ends with a `:' (semicolon), following lines are parsed as in usual Python syntax, or, if the statement ends with a `{' (left brace), following lines are parsed with non-indentation defined, C-ish syntax. So: def fibonacci(n): x, y, z = 1, 1, 0 for i in range(1, n): z = x x += y y = x return x could be also written as def fibonacci(n) { x, y, z = 1, 1, 0; for i in range(1, n) { z = x; x += y; y = x; } return x; } which is a) subject of a different thread, and b) ridiculous. -gk On 30 July 2013 18:19, Musical Notation <musicdenotation@gmail.com> wrote:
participants (17)
-
Andrew Barnert
-
Antoine Pitrou
-
David Mertz
-
Ethan Furman
-
Göktuğ Kayaalp
-
Haoyi Li
-
Masklinn
-
Matthew Lefavor
-
Michael Walter
-
Musical Notation
-
Nick Coghlan
-
Paul Moore
-
Ron Adam
-
Ronald Oussoren
-
Ryan
-
Steven D'Aprano
-
Terry Reedy