Re: [Python-ideas] Ruby-style Blocks in Python Idea (alternative)

This being python-ideas, I'll also have a go at it. Being someone who does like functional programing when used in limited quantities, I also think multi line lambdas (or blocks, whatever you call them) are a good thing if a good way could be found to embed them into Python. But I don't like the part of tavs proposal of handling them with a magic __do__ function. So what about this slightly modified syntax and semantics: def NAME(ARGS) [as OTHERNAME] with EXPRESSION_CONTAINING_NAME: BODY eg: def callback(param) as result with do_something(with_our(callback), other, args): print("called back with "+param) return foobar(param) this would be equivalent to def callback(param): print("called back with "+param) return foobar(param) result = do_something(with_our(callback), other_args) This example tav gave for url in urls: using pool.execute do: print "%s fetching %s" % (time.asctime(), url) httpc.get(url) print "%s fetched %s" % (time.asctime(), url) would be written as for url in urls: def fetch(url) with pool.execute(fetch): print "%s fetching %s" % (time.asctime(), url) httpc.get(url) print "%s fetched %s" % (time.asctime(), url) Compared to tavs proposal this would: - allow for use in expressions where the block is not the only argument, the block could even be passed in multiple parameter positions - make it clear that a function is being defined, and this syntax even allows for re-using the function later on, including testing etc. - not use any new keywords, as it is both syntactically and semantically an extension of the 'def' keyword. I think it also caters to those circumstances where you'd want to use a multiline lambda, without having the awkward reordering of first having to define the function and then passing it by name where the emphasis has to be on what you do with the function (analogous to decorators). It also does everything (I think) that Rubys blocks do. It does not solve the case where you'd want to pass multiple blocks/multiline lambdas to a function, but hey, you can't solve everything. There are several variations of this syntax that could also be considered, eg having the 'with' clause before the 'as' clause, or making the 'with' clause optional as well. Or doing 'using foo(callback, other, args) as answer with callback(param):', that would require a new keyword, but would allow the expression using the new function to be first, as it is presumably the most important part. my €0,02, - Jan

On Mar 9, 2009, at 9:13 PM, Jan Kanis wrote:
Not only the equivalent code looks much cleaner, the only good thing it actually do (not having to first define a function to then use it) can be accomplished with a decorator. Thanks GvR and all that finally shed some light in ruby blocks. I never understood what was so special about them, now I know it is nothing really. :) -- Leonardo Santagada santagada at gmail.com

Leonardo Santagada wrote:
I completely agree.
If a decolib were ever assembled, a callback(receiving_func, args) would be a good one to include. I think I understand now that one of the reasons to use a decorator is to say what you are going to do with a function before you define it so that the person reading the definition can read it in that light. What I like is that the decorator form still leaves the definition cleanly separate from the context. tjr

Le Tue, 10 Mar 2009 01:13:42 +0100, Jan Kanis <jan.kanis@phil.uu.nl> s'exprima ainsi:
I like this proposal much more than all previous ones. Still, how would you (or anybody else) introduce the purpose, meaning, use of this construct, and its language-level semantics? [This is not disguised critics, neither rethoric question: I'm really interested in answers.] Denis ------ la vita e estrany

On Tue, Mar 10, 2009 at 1:58 AM, spir <denis.spir@free.fr> wrote:
Just to avoid getting your hopes up too high, this gets a solid -1 from me, since it just introduces unwieldy new additions to the currently clean 'def' syntax, to accomplish something you can already do just as easily with a decorator. -- --Guido van Rossum (home page: http://www.python.org/~guido/)

On Tue, Mar 10, 2009 at 09:58, spir <denis.spir@free.fr> wrote:
The language level semantics are easily explained by showing the equivalent code I gave in my first mail. The purpose and use (and meaning?) are the same as with tavs original proposal for blocks, and with those of multistatement lambdas. So I guess a major consideration is whether someone thinks multiline lambdas are in principle a good idea (setting aside that they can't be implemented in full generality non-ugly in the python grammar). On Tue, Mar 10, 2009 at 17:33, Guido van Rossum <guido@python.org> wrote:
... to accomplish something you can already do just as easily with a decorator.
Almost the same thing could be done with decorators, the difference being that the final name the result is assigned to occurs in a weird place, and that decorators are restricted to one-argument functions. The first could be solved by allowing an 'as name' clause on decorators (like Carl Johnson is proposing in the other thread), the second by e.g. allowing lambdas as decorators so one could do @lambda f: do_something(with_our(f)) def result(param): print("called back with "+param) return foobar(param) But I don't really have a specific actual use case for this, so I think I'll just have to go with Guidos gut feeling[1], they seem to work out, usually. [1] http://www.python.org/dev/peps/pep-0318/#id32

Jan Kanis wrote:
To keep result from stomping on the name, I would expect result to actually be a result rather than a function :-): @lambda f: do_something(with_our(f)) lambda param: print("called back with "+param) return foobar(param)
But I don't really have a specific actual use case for this...
Looks interesting anyway. Joel

On Wed, Mar 11, 2009 at 21:32, Joel Bender <jjb5@cornell.edu> wrote:
'result' is the actual result. To try it out in current python: def do_something(func): print("doing something") return func(41)**2 def id(x): return x @id(lambda f: do_something(f)) def result(param): print("called back with", param) return param + 1 print("result is", result, "should be", 42**2) --> doing something called back with 41 result is 1764 should be 1764 Or did I misinterpret what you were saying?

On Mar 9, 2009, at 9:13 PM, Jan Kanis wrote:
Not only the equivalent code looks much cleaner, the only good thing it actually do (not having to first define a function to then use it) can be accomplished with a decorator. Thanks GvR and all that finally shed some light in ruby blocks. I never understood what was so special about them, now I know it is nothing really. :) -- Leonardo Santagada santagada at gmail.com

Leonardo Santagada wrote:
I completely agree.
If a decolib were ever assembled, a callback(receiving_func, args) would be a good one to include. I think I understand now that one of the reasons to use a decorator is to say what you are going to do with a function before you define it so that the person reading the definition can read it in that light. What I like is that the decorator form still leaves the definition cleanly separate from the context. tjr

Le Tue, 10 Mar 2009 01:13:42 +0100, Jan Kanis <jan.kanis@phil.uu.nl> s'exprima ainsi:
I like this proposal much more than all previous ones. Still, how would you (or anybody else) introduce the purpose, meaning, use of this construct, and its language-level semantics? [This is not disguised critics, neither rethoric question: I'm really interested in answers.] Denis ------ la vita e estrany

On Tue, Mar 10, 2009 at 1:58 AM, spir <denis.spir@free.fr> wrote:
Just to avoid getting your hopes up too high, this gets a solid -1 from me, since it just introduces unwieldy new additions to the currently clean 'def' syntax, to accomplish something you can already do just as easily with a decorator. -- --Guido van Rossum (home page: http://www.python.org/~guido/)

On Tue, Mar 10, 2009 at 09:58, spir <denis.spir@free.fr> wrote:
The language level semantics are easily explained by showing the equivalent code I gave in my first mail. The purpose and use (and meaning?) are the same as with tavs original proposal for blocks, and with those of multistatement lambdas. So I guess a major consideration is whether someone thinks multiline lambdas are in principle a good idea (setting aside that they can't be implemented in full generality non-ugly in the python grammar). On Tue, Mar 10, 2009 at 17:33, Guido van Rossum <guido@python.org> wrote:
... to accomplish something you can already do just as easily with a decorator.
Almost the same thing could be done with decorators, the difference being that the final name the result is assigned to occurs in a weird place, and that decorators are restricted to one-argument functions. The first could be solved by allowing an 'as name' clause on decorators (like Carl Johnson is proposing in the other thread), the second by e.g. allowing lambdas as decorators so one could do @lambda f: do_something(with_our(f)) def result(param): print("called back with "+param) return foobar(param) But I don't really have a specific actual use case for this, so I think I'll just have to go with Guidos gut feeling[1], they seem to work out, usually. [1] http://www.python.org/dev/peps/pep-0318/#id32

Jan Kanis wrote:
To keep result from stomping on the name, I would expect result to actually be a result rather than a function :-): @lambda f: do_something(with_our(f)) lambda param: print("called back with "+param) return foobar(param)
But I don't really have a specific actual use case for this...
Looks interesting anyway. Joel

On Wed, Mar 11, 2009 at 21:32, Joel Bender <jjb5@cornell.edu> wrote:
'result' is the actual result. To try it out in current python: def do_something(func): print("doing something") return func(41)**2 def id(x): return x @id(lambda f: do_something(f)) def result(param): print("called back with", param) return param + 1 print("result is", result, "should be", 42**2) --> doing something called back with 41 result is 1764 should be 1764 Or did I misinterpret what you were saying?
participants (6)
-
Guido van Rossum
-
Jan Kanis
-
Joel Bender
-
Leonardo Santagada
-
spir
-
Terry Reedy