[Python-ideas] @partials = decorators
Ron Adam
ron3200 at gmail.com
Sat Feb 8 23:41:54 CET 2014
On 02/08/2014 11:55 AM, Ron Adam wrote:
>
> On 02/06/2014 05:14 AM, Nick Coghlan wrote:> On 6 February 2014 20:34, Ron
> Adam<ron3200 at gmail.com> wrote:
> 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.
Here's a rough python version... It currently gets tripped up on optional
arguments, but it does work for non optional cases.
I think a builtin, along with the new signatures capabilities could fix
those cases.
(and to address Stevens conserns.. It would be explicit and won't effect
the beginner cases if you don't use the @...
In this example I'm using P. And a builtin function could work just as
well. Although I would like the @ syntax to just work without the function.
It's just a first attempt, with probably a lot of issues to be handled
still, but it does show it's doable.
Cheers,
Ron
#-------------------------------
# A builtin could do this much better.
class P:
def __init__(self, f, *args, **kwds):
self.f = f
self.args = args
self.kwds = kwds
def __call__(self, *args, **kwds):
args = list(self.args) + list(args)
kwds.update(self.kwds)
try:
return self.f(*args, **kwds)
except TypeError:
return self.__class__(self.f, *args, **kwds)
# This the easy way to write decorators!!! :-)
@P
def deco(f, *args):
print("Got: ", args)
return f(*args)
# And a partial function example with it. :-)
@P
@deco
def foo(x, y, z):
return x + y + z
print(foo(1, 2, 3))
print(foo(1, 2)(3))
print(foo(1)(2)(3))
#-------------------------
The output...
ra:~ >python3 partial_deco.py
Got: ()
Got: (1, 2, 3)
6
Got: (1, 2)
Got: (1, 2, 3)
6
Got: (1,)
Got: (1, 2)
Got: (1, 2, 3)
6
More information about the Python-ideas
mailing list