As the issue has been (indirectly) raised again in the recent context manager thread, I would like to propose yet another syntax for multiline lambdas... I know there has been many but I (foolishly?) hope this one is simpler. I do not wish to focus on the usual arguments for and against the usefulness of such a construct (from the archives of the list, I feel that the lack of an attractive syntax is the bigger barrier). Specifically, I suggest that the "def" (and possibly the "class") keyword(s) may be used in an expression context, if immediately surrounded by parentheses. The indentation of the body of the function is given by the indentation of the first line after the def. target = (def f(arg): <...>) add_callback( def callback(arg): <...>) callbacks = { "foo": (def foo(): <...>), # note how the parentheses disambiguate where the last comma belongs "bar": (def bar(): <...>) } As an extra suggestion, one may want to allow not specifying a function name in these contexts: callbacks = { "foo": (def (): <...>) } (in which case the function would be named "<lambda>", of course) but I do not think that this is a critical feature (and it could always be added later). Feel free to critique, Antony
The obvious first step in assessing this particular proposal is to compare it against JSON (just-some-ordinary-notation), CSV (callables-sequestered-as-values), and XML (eXtended-multiline-lambdas). *dodges rotten tomato* -- This is (Monty) Python-ideas, right?
On Tue, Oct 22, 2013 at 9:33 PM, Chris Rebert <pyideas@rebertia.com> wrote:
The obvious first step in assessing this particular proposal is to compare it against JSON (just-some-ordinary-notation), CSV (callables-sequestered-as-values), and XML (eXtended-multiline-lambdas).
The proposal doesn't matter, as long as it has the right TLA... or, as in this case, ETLA (extended...). After all, there are only two fundamentally difficult problems in computing: cache invalidation, and naming things, and off-by-one errors. And nice red uniforms... ChrisA
On Tue, Oct 22, 2013 at 03:10:29AM -0700, Antony Lee wrote:
Specifically, I suggest that the "def" (and possibly the "class") keyword(s) may be used in an expression context, if immediately surrounded by parentheses.
I don't think there is any need to allow class in an expression, since we already have type().
The indentation of the body of the function is given by the indentation of the first line after the def.
I presume that means you can't do this: value = [1, 2, 3, (def spam(arg): do_this() do_that() ), 4, 5, 6] I think I would be okay with that, since you can't do that with the def statement either: py> def spam(): do_this() ... do_that() File "<stdin>", line 2 do_that() ^ IndentationError: unexpected indent I suppose, like the statement version, a single-line function body could be inline: value = [1, 2, 3, (def spam(arg): do_this()), 4, 5, 6] which would then make lambda redundant. In each of your examples, you have the body indented further to the right than the def. Is that mandatory, or would you allow something like this? value = [1, 2, 3, (def spam(arg): do_this() do_that() if condition(): do_something_else() ), 4, 5, 6, ] That is, relative to the def itself, the body is outdented. I can't see any reason to justify prohibiting the above in the language, although I'd probably frown upon it in style-guides. I think that should be written as: value = [1, 2, 3, (def spam(arg): do_this() do_that() if condition(): do_something_else() ), 4, 5, 6, ] sort of thing. But I don't think that having the first indent be to the left of the def should be prohibited. However, that can lead to some pretty ugly, and misleading, constructions: def spam(arg, func=(def ham(a, x, y, z): fe(a) fi(x) fo(y) fum(z) ), ): ... I'm not sure if there is a question buried in this, or just an observation. I hardly ever miss having multi-line lambdas, and I fear that they will make code harder to read and understand. -- Steven
2013/10/22 Steven D’Aprano <steve@pearwood.info> which would then make lambda redundant. no, lambda still doesn’t need a return statement, returning the result of its only expression. so we could do x = (def (a): a)assert x('b') == None and x = lambda a: aassert x('b') == 'b' and about your “misleading constructions”: the ability to put arguments of function definitions on their own lines is already ugly. we basically have no switch statement because it would be indented twice or half, but we indent twice or half when defining functions all the time. and if your default argument is a function, you’ll definitely want it to be a simple one anyway or would use the tried def a(f=None): if default is None: def f(): ...
On Oct 22, 2013, at 5:39, Steven D'Aprano <steve@pearwood.info> wrote:
On Tue, Oct 22, 2013 at 03:10:29AM -0700, Antony Lee wrote:
Specifically, I suggest that the "def" (and possibly the "class") keyword(s) may be used in an expression context, if immediately surrounded by parentheses.
I don't think there is any need to allow class in an expression, since we already have type().
But type doesn't allow you to do most of what you can do in a class definition. This is like arguing that we don't need expression def because we already have types.FunctionType.
The indentation of the body of the function is given by the indentation of the first line after the def.
I presume that means you can't do this:
value = [1, 2, 3, (def spam(arg): do_this() do_that() ), 4, 5, 6]
I think I would be okay with that, since you can't do that with the def statement either:
py> def spam(): do_this() ... do_that() File "<stdin>", line 2 do_that() ^ IndentationError: unexpected indent
I suppose, like the statement version, a single-line function body could be inline:
value = [1, 2, 3, (def spam(arg): do_this()), 4, 5, 6]
which would then make lambda redundant.
In each of your examples, you have the body indented further to the right than the def. Is that mandatory, or would you allow something like this?
value = [1, 2, 3, (def spam(arg): do_this() do_that() if condition(): do_something_else() ), 4, 5, 6, ]
That is, relative to the def itself, the body is outdented.
I can't see any reason to justify prohibiting the above in the language, although I'd probably frown upon it in style-guides. I think that should be written as:
value = [1, 2, 3, (def spam(arg): do_this() do_that() if condition(): do_something_else() ), 4, 5, 6, ]
sort of thing. But I don't think that having the first indent be to the left of the def should be prohibited. However, that can lead to some pretty ugly, and misleading, constructions:
def spam(arg, func=(def ham(a, x, y, z): fe(a) fi(x) fo(y) fum(z) ), ): ...
I'm not sure if there is a question buried in this, or just an observation. I hardly ever miss having multi-line lambdas, and I fear that they will make code harder to read and understand.
-- Steven _______________________________________________ Python-ideas mailing list Python-ideas@python.org https://mail.python.org/mailman/listinfo/python-ideas
On Tue, Oct 22, 2013 at 09:27:59AM -0700, Andrew Barnert wrote:
On Oct 22, 2013, at 5:39, Steven D'Aprano <steve@pearwood.info> wrote:
On Tue, Oct 22, 2013 at 03:10:29AM -0700, Antony Lee wrote:
Specifically, I suggest that the "def" (and possibly the "class") keyword(s) may be used in an expression context, if immediately surrounded by parentheses.
I don't think there is any need to allow class in an expression, since we already have type().
But type doesn't allow you to do most of what you can do in a class definition. This is like arguing that we don't need expression def because we already have types.FunctionType.
Given multi-line lambda, what could you do in a class definition that you couldn't do with type? class Spam(SpamBase, HamBase): x = 1 def eggs(self, arg): return arg+self.x classes = [int, str, Spam, float] would become: classes = [int, str, type('Spam', (SpamBase, HamBase), {'x': 1, 'eggs': (def eggs(self, arg): return arg+self.x ), } ), float, ] which I personally don't consider an improvement, but some people might. You could even handle metaclasses and extra arguments: class Spam(SpamBase, metaclass=MetaSpam, extrakw="extra"): ... becomes: MetaSpam('Spam', (SpamBase,), {...}, extrakw="extra") so given a def expression, I don't think we also need a class expression. What's missing? -- Steven
On Oct 22, 2013, at 11:07, Steven D'Aprano <steve@pearwood.info> wrote:
On Tue, Oct 22, 2013 at 09:27:59AM -0700, Andrew Barnert wrote:
On Oct 22, 2013, at 5:39, Steven D'Aprano <steve@pearwood.info> wrote:
On Tue, Oct 22, 2013 at 03:10:29AM -0700, Antony Lee wrote:
Specifically, I suggest that the "def" (and possibly the "class") keyword(s) may be used in an expression context, if immediately surrounded by parentheses.
I don't think there is any need to allow class in an expression, since we already have type().
But type doesn't allow you to do most of what you can do in a class definition. This is like arguing that we don't need expression def because we already have types.FunctionType.
Given multi-line lambda, what could you do in a class definition that you couldn't do with type?
Write code that's somewhat readable and looks somewhat like Python?
class Spam(SpamBase, HamBase): x = 1 def eggs(self, arg): return arg+self.x
classes = [int, str, Spam, float]
would become:
classes = [int, str, type('Spam', (SpamBase, HamBase), {'x': 1, 'eggs': (def eggs(self, arg): return arg+self.x ), } ), float, ]
which I personally don't consider an improvement, but some people might.
Anyone who finds that an improvement clearly would rather be using a different language than python in the first place.
You could even handle metaclasses and extra arguments:
class Spam(SpamBase, metaclass=MetaSpam, extrakw="extra"): ...
becomes:
MetaSpam('Spam', (SpamBase,), {...}, extrakw="extra")
so given a def expression, I don't think we also need a class expression. What's missing?
-- Steven _______________________________________________ Python-ideas mailing list Python-ideas@python.org https://mail.python.org/mailman/listinfo/python-ideas
On Wed, Oct 23, 2013 at 12:53:13AM -0700, Andrew Barnert wrote:
But type doesn't allow you to do most of what you can do in a class definition. This is like arguing that we don't need expression def because we already have types.FunctionType.
Given multi-line lambda, what could you do in a class definition that you couldn't do with type?
Write code that's somewhat readable and looks somewhat like Python?
No, that's not it. You can certainly write somewhat readable code that looks like Python using type. But definition, calls to type() look like Python code, because they *are* Python code. So I'm still curious as to what you can do in a class statement that couldn't be done in a call to type. The only thing I can think of is that class statement introduces a new scope, while type does not, so you can compute class attributes without affecting names in the enclosing scope: x = 42 y = 23 class Spam: x = "something" y = x.upper() + "!" assert x == 42 and y == 23 In the most general case, this would be rather tricky using type, without introducing extraneous variables. But I don't see this as a real problem for the suggestion. Nobody has come up with any major problems with this suggestion other than (1) it isn't strictly necessary, and (2) non-trivial function-expressions don't look very nice. I'm afraid I'm no different: although I can't find anything obviously wrong with the suggestion, nor can I develop much enthusiasm for it. I haven't used Ruby enough to really see the big deal for anonymous multi-line code blocks. I will say one thing: I do like the fact that this suggestion gives the functions a name, rather than making them anonymous. One disadvantage of lambda is that the lack of name makes it harder to debug them. That's not a problem in this case. So... +0 on named def expressions; -0 on anonymous def expressions; -1 on class expressions. -- Steven
On Oct 23, 2013, at 5:50, Steven D'Aprano <steve@pearwood.info> wrote:
Write code that's somewhat readable and looks somewhat like Python?
No, that's not it. You can certainly write somewhat readable code that looks like Python using type. But definition, calls to type() look like Python code, because they *are* Python code.
Not everything that is executable as python looks like python. That's why we have the word "pythonic". Defining a class by building a dict to pass to the type function is not the way you define classes in Python, except in uncommon cases where you need to create classes based on dynamic information. Suggesting that it should be the idiomatic way of creating "local" or "inline" classes is like suggesting that exec('='.join(map(chr,range(97,40,-47)))) or locals().update(dict([map(chr,range(97,40,-47))])) or something should be the idiomatic way to assign 2 to x in some context. (After all, the only semantic difference is a minor scope-related issue--if this is the only assignment to x in a scope the compiler won't be able to tell that it's a local variable.) Unless this is a roundabout way of arguing that there shouldn't be an idiomatic way to define inline classes in the first place?
On Tuesday, October 22, 2013 5:39:03 AM UTC-7, Steven D'Aprano wrote:
On Tue, Oct 22, 2013 at 03:10:29AM -0700, Antony Lee wrote:
Specifically, I suggest that the "def" (and possibly the "class") keyword(s) may be used in an expression context, if immediately surrounded by parentheses.
I don't think there is any need to allow class in an expression, since we already have type().
I don't actually think that extending the "class" statement is that useful, but felt that given the similarity between class and def, I may as well mention it. The main point here is really the "def" statement.
The indentation of the body of the function is given by the indentation of the first line after the def.
I presume that means you can't do this:
value = [1, 2, 3, (def spam(arg): do_this() do_that() ), 4, 5, 6]
I think I would be okay with that, since you can't do that with the def statement either:
py> def spam(): do_this() ... do_that() File "<stdin>", line 2 do_that() ^ IndentationError: unexpected indent
Yes, that is the intent.
I suppose, like the statement version, a single-line function body could be inline:
value = [1, 2, 3, (def spam(arg): do_this()), 4, 5, 6]
which would then make lambda redundant.
While TOOWTDI, I think it is somewhat agreed that lambda's syntax is a bit a kludge, so perhaps we should try to find a replacement.
In each of your examples, you have the body indented further to the right than the def. Is that mandatory, or would you allow something like this?
value = [1, 2, 3, (def spam(arg): do_this() do_that() if condition(): do_something_else() ), 4, 5, 6, ]
That is, relative to the def itself, the body is outdented.
I would allow this on grounds of grammar simplicity (but perhaps strongly discourage it in a style guide).
I can't see any reason to justify prohibiting the above in the language, although I'd probably frown upon it in style-guides. I think that should be written as:
value = [1, 2, 3, (def spam(arg): do_this() do_that() if condition(): do_something_else() ), 4, 5, 6, ]
sort of thing. But I don't think that having the first indent be to the left of the def should be prohibited. However, that can lead to some pretty ugly, and misleading, constructions:
def spam(arg, func=(def ham(a, x, y, z): fe(a) fi(x) fo(y) fum(z) ), ): ...
I'm not sure if there is a question buried in this, or just an observation. I hardly ever miss having multi-line lambdas, and I fear that they will make code harder to read and understand.
-- Steven _______________________________________________ Python-ideas mailing list Python...@python.org <javascript:> https://mail.python.org/mailman/listinfo/python-ideas
On Oct 22, 2013, at 3:10, Antony Lee <antony.lee@berkeley.edu> wrote:
Specifically, I suggest that the "def" (and possibly the "class") keyword(s) may be used in an expression context, if immediately surrounded by parentheses. The indentation of the body of the function is given by the indentation of the first line after the def.
I don't think this idea will fit well with Python's OO. Partly this is based on JS experience, where you have to write .bind(this) all over the place because your callback--or, worse, some callback later in the chain--needs access to this. In Python, f.bind(this) is spelled types.MethodType(f, self, type(self)), and classes are used more than in JS rather than less. Especially since the paradigm cases for callbacks--network transports, GUI events, etc.--are also paradigm cases for objects--protocols, controllers, etc. At best this will lead to two completely different styles for doing things that are hard to tie together. At worst people will tie them together the same way they usually do in JS, leading to ugly circumlocutions where people bind self to other variables in closures (like the common "that = this" in JS), wrap functions in extra lambdas just to turn them into methods, or use partial to do the same, etc., to avoid the need to bind(this) at every step on the chain. And the fact that you can often rely on capturing self directly in a closure doesn't make things better, but worse, because it's not nearly often enough to count on. In fact, I'd go so far as to say that not having inline def is part of the reason python server code is usually easier to read than node server code, despite node having an API not that far from Python frameworks like Twisted. As a secondary concern, this would make it harder to partially parse Python the way IDEs and other code managing tools often do.
I don't have any experience with JS, so perhaps I don't understand the issues well... but if you define a callback in a method, you don't need to call "bind" as "self" will be captured as a closure variable anyways (in particular, can you explain what you mean by "this would make things worse"?). Also, if you really need to bind the first variable and don't want to use partial, you can also use __get__, which exactly creates bound methods: (lambda x: x).__get__(1)() ==> 1. Also, the syntax (in particular the extra parentheses) was specifically chosen to make parsing relatively easy (avoiding awkward issues of "when does the 'def' end?"). PS: I'm using the Google Groups interface and feel like I'm making a mess of the email layouts. Any hints on whether this can be avoided -- or do I have to go through mailman instead? Antony On Tuesday, October 22, 2013 9:52:31 AM UTC-7, Andrew Barnert wrote:
On Oct 22, 2013, at 3:10, Antony Lee <anton...@berkeley.edu <javascript:>> wrote:
Specifically, I suggest that the "def" (and possibly the "class") keyword(s) may be used in an expression context, if immediately surrounded by parentheses. The indentation of the body of the function is given by the indentation of the first line after the def.
I don't think this idea will fit well with Python's OO.
Partly this is based on JS experience, where you have to write .bind(this) all over the place because your callback--or, worse, some callback later in the chain--needs access to this.
In Python, f.bind(this) is spelled types.MethodType(f, self, type(self)), and classes are used more than in JS rather than less. Especially since the paradigm cases for callbacks--network transports, GUI events, etc.--are also paradigm cases for objects--protocols, controllers, etc. At best this will lead to two completely different styles for doing things that are hard to tie together. At worst people will tie them together the same way they usually do in JS, leading to ugly circumlocutions where people bind self to other variables in closures (like the common "that = this" in JS), wrap functions in extra lambdas just to turn them into methods, or use partial to do the same, etc., to avoid the need to bind(this) at every step on the chain. And the fact that you can often rely on capturing self directly in a closure doesn't make things better, but worse, because it's not nearly often enough to count on.
In fact, I'd go so far as to say that not having inline def is part of the reason python server code is usually easier to read than node server code, despite node having an API not that far from Python frameworks like Twisted.
As a secondary concern, this would make it harder to partially parse Python the way IDEs and other code managing tools often do. _______________________________________________ Python-ideas mailing list Python...@python.org <javascript:> https://mail.python.org/mailman/listinfo/python-ideas
On Oct 22, 2013, at 12:13, Antony Lee <anntzer.lee@gmail.com> wrote:
Also, if you really need to bind the first variable and don't want to use partial, you can also use __get__, which exactly creates bound methods: (lambda x: x).__get__(1)() ==> 1.
Do you think this is something that most Python users would understand today, or do you think Python would be a better language if it were a recognized idiom? I'll answer the other part when I'm in front of a computer.
I'm sorry I raised the inline class idea, which is distracting the main issue here -- inline functions (again, all I wanted to do was to point out the syntactic similarity). I certainly don't think that creating bound methods through __get__ is a particularly recognized idiom (although one may note that descriptors were (I believe) introduced exactly for that purpose); on the other hand as I mentioned earlier I don't really see the need for binding lambdas to objects in the first place. Antony On Wednesday, October 23, 2013 12:57:46 AM UTC-7, Andrew Barnert wrote:
On Oct 22, 2013, at 12:13, Antony Lee <anntz...@gmail.com <javascript:>> wrote:
Also, if you really need to bind the first variable and don't want to use partial, you can also use __get__, which exactly creates bound methods: (lambda x: x).__get__(1)() ==> 1.
Do you think this is something that most Python users would understand today, or do you think Python would be a better language if it were a recognized idiom?
I'll answer the other part when I'm in front of a computer. _______________________________________________ Python-ideas mailing list Python...@python.org <javascript:> https://mail.python.org/mailman/listinfo/python-ideas
Antony Lee writes:
as I mentioned earlier I don't really see the need
It's not a *need*, it's a *style*. Ie, it's just the way Pythonistas do things. Many fledgling Pythonistas, especially those who come from other languages, hanker after anonymous functions or Ruby blocks (a somewhat different concept AFAICT), and some experienced Pythonistas sympathize with them. But there's no real reason why some functions shouldn't have a name, and Guido (the ultimate authority on "Pythonic") isn't a fan of lambda, so (unless a pressing need or a really good syntax appears) there seems to be little chance of the existing feature (expressions as lambdas) being extended.
for binding lambdas to objects in the first place.
I think you've misspoken here. Lambdas *are* objects, and that's why names can be bound to them (and then they're called "functions"). What people complain about is the fact that the normal way to create a lambda (callable function object or something like that) is "def", which also binds a name to the object. They think that is wasteful or something. Steve
2013/10/24 Stephen J. Turnbull <stephen@xemacs.org>
Antony Lee writes:
as I mentioned earlier I don't really see the need
It's not a *need*, it's a *style*. Ie, it's just the way Pythonistas do things.
Many fledgling Pythonistas, especially those who come from other languages, hanker after anonymous functions or Ruby blocks (a somewhat different concept AFAICT), and some experienced Pythonistas sympathize with them. But there's no real reason why some functions shouldn't have a name, and Guido (the ultimate authority on "Pythonic") isn't a fan of lambda, so (unless a pressing need or a really good syntax appears) there seems to be little chance of the existing feature (expressions as lambdas) being extended.
I think you've misunderstood the aim of my proposal. While my proposal does contain the possibility, as a syntax extension, to define anonymous lambdas (or functions, if you prefer), in the middle of an expression (as opposed to "in a statement"), the core idea is about *named* lambdas (or functions, etc.). From the very beginning I said that allowing the anonymous form ("(def (...): ...)" instead of "(def name(...): ...)") was not a critical part of the proposal.
for binding lambdas to objects in the first place.
I think you've misspoken here. Lambdas *are* objects, and that's why names can be bound to them (and then they're called "functions").
I was specifically referring to Andrew Barnaert's reply, which I quote here: Partly this is based on JS experience, where you have to write .bind(this)
all over the place because your callback--or, worse, some callback later in the chain--needs access to this.
Specifically, I was asking his to clarify the relevance of such an issue as a locally defined lambda (etc.) already captures "self" without the need for a call to a JS-like bind (which is effectively spelled __get__ in Python).
What people complain about is the fact that the normal way to create a lambda (callable function object or something like that) is "def", which also binds a name to the object. They think that is wasteful or something.
No, that is not what I complain about. Just look at the other currently active thread on context manager semantics, where Nick Coghlan said it *also* means that we *don't* currently have a clean syntax for single
use callbacks.
Hence the time I've put into PEP 403 and 3150 over the years - a key objective for both of them is providing a cleaner solution for the problem of single use callbacks (including those that modify local variables of the containing function).
Another example is when you want to provide a dictionary of callbacks (e.g. to be triggered by various command line options), say at global scope, without putting the callbacks themselves in that scope). See Serhiy Storchaka's suggestion on why multiline lambdas are not essential here:
callbacks = {
"foo": (def foo(): <...>), # note how the parentheses disambiguate where the last comma belongs "bar": (def bar(): <...>) }
def class_to_map(cls): return {n: f for n, f in cls.__dict__items() if n[0] != '_'}
@class_to_map class callbacks: @staticmethod def foo(): ... @staticmethod def bar(): ...
I don't think abusing the class statement is particularly elegant either (and good luck if you want to preserve order... what, I have to provide a metaclass that overrides __prepare__ for doing this?), and moreover this solution doesn't even work as it is written (it needs a small fix... quick, can you spot it)?
Steve
Antony
Antony Lee <anntzer.lee@gmail.com> writes:
2013/10/24 Stephen J. Turnbull <stephen@xemacs.org>
I think you've misunderstood the aim of my proposal.
No, I misunderstood the language in your most recent post, not to mention the consistent mis-specification of the whole idea in *every* subject line. Python doesn't currently have a notion of "binding" lambdas to objects, and you here don't specify how a lambda (object) is being "bound" to what (other kind of) object. Python does have a notion of binding names to objects. Confusion is natural. If you're *primarily* talking about defining functions in the "right place" in general, what's wrong with using the well-defined Python terms for those objects?
Specifically, I was asking his to clarify the relevance of such an issue as a locally defined lambda (etc.) already captures "self" without the need for a call to a JS-like bind (which is effectively spelled __get__ in Python).
Sure. So there is no "need" in the first place. I don't understand what you're talking about. IMO Nick's use case, described next, is compelling. Why not just say "this syntax does the trick for that use case"? Are you saying anything else? That's what I can't figure out.
Just look at the other currently active thread on context manager semantics, where Nick Coghlan said
it *also* means that we *don't* currently have a clean syntax for single use callbacks.
Another example is when you want to provide a dictionary of callbacks (e.g. to be triggered by various command line options), say at global scope, without putting the callbacks themselves in that scope).
Eh, "there you go again." That's the same example, isn't it? It's a good one and stands repeating, but it's not different. In both cases you have a callback and a desire to put the def in an appropriate "place" (namespace, and often lexical position in the source). The dictionary of callbacks idiom is familiar (at least to those of us to have the misfortune to program with Xt), and I certainly understand the desire to define callbacks in an appropriate scope. Again, do you have *more* to say than "I think my syntax does this nicely, concisely, and precisely"? If you have other compelling use cases, that would be useful. But I think the "defining callbacks in the right place" use case would be enough to get this proposal in Python 3.5 (if it stands up to issues like the LL constraint on the languages, and the objection to YAAP[1]). Mixing this up with "lambda" and "binding" is unhelpful AFAICS.
I don't think abusing the class statement is particularly elegant either (and good luck if you want to preserve order... what, I have to provide a metaclass that overrides __prepare__ for doing this?),
I doubt you need to use a metaclass (storing the callbacks in an OrderedDict and then defining an appropriate __index__ can probably be done with a decorator or two), but the alternatives are hardly prettier I guess. Footnotes: [1] Yet Another Abuse of Parentheses, also spelled "YAAPMILL" ("... Making It Like LISP").
On Oct 24, 2013, at 3:10, "Stephen J. Turnbull" <stephen@xemacs.org> wrote:
Antony Lee writes:
as I mentioned earlier I don't really see the need
It's not a *need*, it's a *style*. Ie, it's just the way Pythonistas do things.
Many fledgling Pythonistas, especially those who come from other languages, hanker after anonymous functions or Ruby blocks (a somewhat different concept AFAICT), and some experienced Pythonistas sympathize with them. But there's no real reason why some functions shouldn't have a name, and Guido (the ultimate authority on "Pythonic") isn't a fan of lambda, so (unless a pressing need or a really good syntax appears) there seems to be little chance of the existing feature (expressions as lambdas) being extended.
for binding lambdas to objects in the first place.
I think you've misspoken here. Lambdas *are* objects, and that's why names can be bound to them (and then they're called "functions"). What people complain about is the fact that the normal way to create a lambda (callable function object or something like that) is "def", which also binds a name to the object. They think that is wasteful or something.
I think the desire for this feature is less about the name issue, and more about two other issues. The big issue is that you can't put a statement in an expression. Python has a much stricter statement/expression barrier than most languages. Python also has a nice separation between its declarative subset and the rest of the language. And it ties these two things together: composable expressions don't have side effects. All of this contributes a lot to Python's readability. But it can be limiting. If you want to throw a side effect like updating a variable into the middle of an expression--whether it's a listcomp or a lambda callback--you can't. In Ruby, JavaScript, the main .NET languages, and even some of the impure traditional functional languages, doing that kind of thing is not just allowed, but idiomatic. That's why all of these proposals are about a way to embed a statement context (a "multiline lambda" or "inline def") into the middle of an expression. There's also an order-of-definition problem. You want to put code where it belongs, and to avoid highlighting code that isn't the important part of your logic. When you write a call to async_read() or Button() with a trivial callback, it's easier to understand if the callback is inside the call (which is why we have lambdas in the first place). Nick Coghlan's two @in PEPs are about providing this feature without the previous one (and I think it's significant that they've attracted much less dislike, but also less positive excitement).
On 25 Oct 2013 03:06, "Andrew Barnert" <abarnert@yahoo.com> wrote:
On Oct 24, 2013, at 3:10, "Stephen J. Turnbull" <stephen@xemacs.org>
wrote:
Antony Lee writes:
as I mentioned earlier I don't really see the need
It's not a *need*, it's a *style*. Ie, it's just the way Pythonistas do things.
Many fledgling Pythonistas, especially those who come from other languages, hanker after anonymous functions or Ruby blocks (a somewhat different concept AFAICT), and some experienced Pythonistas sympathize with them. But there's no real reason why some functions shouldn't have a name, and Guido (the ultimate authority on "Pythonic") isn't a fan of lambda, so (unless a pressing need or a really good syntax appears) there seems to be little chance of the existing feature (expressions as lambdas) being extended.
for binding lambdas to objects in the first place.
I think you've misspoken here. Lambdas *are* objects, and that's why names can be bound to them (and then they're called "functions"). What people complain about is the fact that the normal way to create a lambda (callable function object or something like that) is "def", which also binds a name to the object. They think that is wasteful or something.
I think the desire for this feature is less about the name issue, and
more about two other issues.
The big issue is that you can't put a statement in an expression. Python
has a much stricter statement/expression barrier than most languages. Python also has a nice separation between its declarative subset and the rest of the language. And it ties these two things together: composable expressions don't have side effects. All of this contributes a lot to Python's readability. But it can be limiting. If you want to throw a side effect like updating a variable into the middle of an expression--whether it's a listcomp or a lambda callback--you can't. In Ruby, JavaScript, the main .NET languages, and even some of the impure traditional functional languages, doing that kind of thing is not just allowed, but idiomatic. That's why all of these proposals are about a way to embed a statement context (a "multiline lambda" or "inline def") into the middle of an expression.
There's also an order-of-definition problem. You want to put code where
it belongs, and to avoid highlighting code that isn't the important part of your logic. When you write a call to async_read() or Button() with a trivial callback, it's easier to understand if the callback is inside the call (which is why we have lambdas in the first place). Nick Coghlan's two @in PEPs are about providing this feature without the previous one (and I think it's significant that they've attracted much less dislike, but also less positive excitement). Right, when people get excited about Ruby's "blocks" and say Python should have something equivalent, they can actually be talking about two subtly different things: - the block statement (do/end) which handles single use callbacks nicely - inline blocks which let you embed callbacks with side effects on name bindings in the local namespace inside expressions The functional programming influence on Python at the expression level is strong enough for me to say "no, we almost certainly don't want to go there" (but see the postscript below). The first would definitely be a nice problem to resolve, though. Cheers, Nick. P.S. http://python-notes.curiousefficiency.org/en/latest/pep_ideas/suite_expr.htm...
_______________________________________________ Python-ideas mailing list Python-ideas@python.org https://mail.python.org/mailman/listinfo/python-ideas
Looks like Lisp(Lots of Irritating Stupid Parenthesis). Hehehe. On Tue, Oct 22, 2013 at 5:10 AM, Antony Lee <antony.lee@berkeley.edu> wrote:
As the issue has been (indirectly) raised again in the recent context manager thread, I would like to propose yet another syntax for multiline lambdas... I know there has been many but I (foolishly?) hope this one is simpler. I do not wish to focus on the usual arguments for and against the usefulness of such a construct (from the archives of the list, I feel that the lack of an attractive syntax is the bigger barrier).
Specifically, I suggest that the "def" (and possibly the "class") keyword(s) may be used in an expression context, if immediately surrounded by parentheses. The indentation of the body of the function is given by the indentation of the first line after the def.
target = (def f(arg): <...>)
add_callback( def callback(arg): <...>)
callbacks = { "foo": (def foo(): <...>), # note how the parentheses disambiguate where the last comma belongs "bar": (def bar(): <...>) }
As an extra suggestion, one may want to allow not specifying a function name in these contexts:
callbacks = { "foo": (def (): <...>) }
(in which case the function would be named "<lambda>", of course) but I do not think that this is a critical feature (and it could always be added later).
Feel free to critique,
Antony
_______________________________________________ Python-ideas mailing list Python-ideas@python.org https://mail.python.org/mailman/listinfo/python-ideas
-- Ryan
22.10.13 13:10, Antony Lee написав(ла):
As the issue has been (indirectly) raised again in the recent context manager thread, I would like to propose yet another syntax for multiline lambdas...
Most of use cases for multiline lambdas actually don't needed multiline lambdas.
target = (def f(arg): <...>)
def target(arg): ...
callbacks = { "foo": (def foo(): <...>), # note how the parentheses disambiguate where the last comma belongs "bar": (def bar(): <...>) }
def class_to_map(cls): return {n: f for n, f in cls.__dict__items() if n[0] != '_'} @class_to_map class callbacks: @staticmethod def foo(): ... @staticmethod def bar(): ...
participants (11)
-
Andrew Barnert
-
Antony Lee
-
Antony Lee
-
Chris Angelico
-
Chris Rebert
-
Nick Coghlan
-
Philipp A.
-
Ryan Gonzalez
-
Serhiy Storchaka
-
Stephen J. Turnbull
-
Steven D'Aprano