returning anonymous functions
It is a very common case to return a nested function, e.g. in a decorator: def deco(f): def _f(*args,**kwargs): do_something() try: return f(*args,**kwargs) finally: do_something_different() return _f While I agree that the current way with non-anonymous functions perfectly works, it looks ugly to a lot of people. Maybe one of these syntax variants would be an option: def deco(f): return def(*args,**kwargs): do_something() try: return f(*args,**kwargs) finally: do_something_different() def deco(f): return(*args,**kwargs): do_something() try: return f(*args,**kwargs) finally: do_something_different() def deco(f): def return(*args,**kwargs): do_something() try: return f(*args,**kwargs) finally: do_something_different() Ok, the last one is not serious. This would not be some kind of anonymous function expression but an extended form of the return statement. Maybe you could do the same thing for yield? Well, I guess not, because yield can have a return value and this would be awkward: x = yield(a,b): return a + b And this would not be an option: f(yield(a,b): return a + b) But extending return and not extending yield feels wrong. What do you think? Does anyone have a better idea or is the current way the only thinkable for python (which might very well be the case)? -panzi
Mathias Panzenböck wrote:
It is a very common case to return a nested function, e.g. in a decorator:
def deco(f): def _f(*args,**kwargs): do_something() try: return f(*args,**kwargs) finally: do_something_different() return _f
Is is really that common? In this case, you are misrepresenting the pattern. The appropriate version of this would require references to _f to make it's signature match that of f's, and therefore this entire argument is specious. In reality, the number of times you can get away with returning a truly anonymous function (that isn't a glorified lambda) is rare, I think. def deco(f): def _f(*args,**kawrgs): ... functools.update_wrapper(_f, f) return _f Or: def deco(f): @functools.wraps(f) def _f(*args,**kawrgs): ... return _f Even in the second case, it would be awkward to inline with the return statement because of the need to invoke a decorator. -Scott -- Scott Dial scott@scottdial.com scodial@cs.indiana.edu
Scott Dial schrieb:
Is is really that common? In this case, you are misrepresenting the pattern. The appropriate version of this would require references to _f to make it's signature match that of f's, and therefore this entire argument is specious. In reality, the number of times you can get away with returning a truly anonymous function (that isn't a glorified lambda) is rare, I think.
def deco(f): def _f(*args,**kawrgs): ... functools.update_wrapper(_f, f) return _f
Or:
def deco(f): @functools.wraps(f) def _f(*args,**kawrgs): ... return _f
Even in the second case, it would be awkward to inline with the return statement because of the need to invoke a decorator.
ic. Ok, maybe something even more different: curried functions. def plus2(f)(x): return f(x+2) @plus2 def foo(x): ... Or I don't know. Just a thought. And yes, you cannot user functools.wraps on that either. And this is just plain ugly/utter crap: def plus2(f) @functools.wraps(f) def (x): return f(x+2) -panzi
Mathias Panzenböck schrieb:
Scott Dial schrieb:
Is is really that common? In this case, you are misrepresenting the pattern. The appropriate version of this would require references to _f to make it's signature match that of f's, and therefore this entire argument is specious. In reality, the number of times you can get away with returning a truly anonymous function (that isn't a glorified lambda) is rare, I think.
def deco(f): def _f(*args,**kawrgs): ... functools.update_wrapper(_f, f) return _f
Or:
def deco(f): @functools.wraps(f) def _f(*args,**kawrgs): ... return _f
Even in the second case, it would be awkward to inline with the return statement because of the need to invoke a decorator.
ic.
Ok, maybe something even more different: curried functions.
def plus2(f)(x): return f(x+2)
@plus2 def foo(x): ...
Or I don't know. Just a thought. And yes, you cannot user functools.wraps on that either. And this is just plain ugly/utter crap:
def plus2(f) @functools.wraps(f) def (x): return f(x+2)
-panzi
Thinking of it, we do not need any new syntax: def curry(f): def _f(x). def _f2(*args,**kwargs): return f(x,*args,**kwargs) return _f2 return _f @curry def foo(a,b,c): return a+b+c Maybe we can somehow also use functools.update_wrapper here. -panzi
On Tue, Dec 16, 2008 at 3:40 AM, Mathias Panzenböck <grosser.meister.morti@gmx.net> wrote:
Thinking of it, we do not need any new syntax:
def curry(f): def _f(x). def _f2(*args,**kwargs): return f(x,*args,**kwargs) return _f2 return _f
@curry def foo(a,b,c): return a+b+c
This forces you to call foo(1)(2)(3) if you want an answer. How about: def curry(f): def _f(*c_args, **c_kwargs): def _f2(*args, **kwargs): return f(*c_args, *args, **c_kwargs, **kwargs) return _f2 return _f @curry def foo(a, b, c): return a + b + c foo(1, 2)(3) I think this still prevents us from currying multiple times --- that is, you curry once, and you get a non-curriable function. I remember something in the wiki about a decorator in the form of an object, that accumulated arguments when __call__()ed, and I think that worked best (and still didn't need new syntax). -- Cheers, Leif
participants (3)
-
Leif Walsh
-
Mathias Panzenböck
-
Scott Dial