[Python-ideas] @partials = decorators
Ron Adam
ron3200 at gmail.com
Sat Feb 8 18:55:56 CET 2014
On 02/06/2014 05:14 AM, Nick Coghlan wrote:> On 6 February 2014 20:34, Ron
Adam<ron3200 at gmail.com> wrote:
(clipped unrelated discussion)
> As far as what you're proposing goes, is it essentially a way to
> declare a function like (spelling out the lambdas fully):
>
> def S(x):
> def _second(y):
> def _third(z):
> return x(z)(y(z))
> return _third
> return _second
>
> As something much shorter like this:
>
> def S (x)(y)(z):
> return x(z)(y(z))
>
> The main potential benefit I could see to a construct like that is
> that it may allow the more consistent creation of closures that
> support pickling, since the outer functions are guaranteed not to have
> any side effects and to have argument capture as their*only*
> significant state. This means that you could take the inner function,
> pickle it along with its closure variables and reconstruct that at the
> far end, only relying on the name of the outer function.
>
> Such a construct could also make decorator factories easier to write.
>
> def decorator(f):
> # Do something with f
>
> def decorator_factory(some, args, here)(f):
> # Do something with f, but have access to the bound args.
>
> There's an argument to be made that the extra parens in the function
> header are too easy to miss, but I still see "make it easier to write
> side-effect free closures" as an idea worth discussing further.
It's a different feature than the one I was suggesting, which was a type of
continuations... but the two concepts are related and compatible.
I think the S(x)(y)(z): is adding more complexity to function signatures
which are already more complex than I like, but there is an alternate
option...
What if these *calls* were equivalent...
S(x, y, z) == S(x)(y)(z)
* There might need to be some additional device or syntax needed to make it
work. (* see '@' comments further down.)
That is on the call side, so the definition would still be the same.
def(x, y, z): ...
Which is nice, because it gives us partials at a lower level which may have
some advantages over a library function. And it gives us a better way to
define decorators.
def deco(func, *args, **kwds):
...
deco(func, *args, **kwds) == deco(func)(*args, **kwds)
or deco(func)(*args)(**kwds)
In effect making a decorators into partials.
@deco
def foo(...):
...
Hmmm... Could the @ syntax be generalised in this case?
@foo(func) Partial waiting for rest...
Then the more general case...
a_op = @foo(op) # Partial waiting for rest.
a_x = @a_op(x)
a = a_x(y)
That would be cool, unifies decorators and partials with decorator syntax!
I think it's even back-words compatible if you allow this equivalency.
def foo(x, y):
...
@foo(x, y) == foo(x, y) # An identity partial
And the decorator case becomes...
@partial
def func():
...
And we get this equivalency as well....
@partial == partial # I think this could work.
The reason these things are interesting to me is that, I've been thinking
about the order of function arguments and if there could be some
generalised concepts that can be applied to that problem. Being able to
use normal functions effectively in these ways, (with partials, and
continuations), is related to the order of the arguments and how they are
commonly used.
Cheers,
Ron
More information about the Python-ideas
mailing list