Partially evaluated functions
Nick Perkins
nperkins7 at home.com
Wed Jun 20 14:16:21 EDT 2001
"Rainer Deyke" <root at rainerdeyke.com> wrote...
> ...
> My version is superior in that it doesn't use named arguments. Consider:
>
> def f(self):
> print self
>
> curry(self = 5) # This will fail with the cookbook version.
>
..Of course, you mean:
curry(f, self=5)
.. which works fine with the cookbook version.
( why wouldn't it? )
> > I notice that that the cookbook version makes a copy of the kwargs
> > dictionary.
> > I suppose this prevents kwargs from being modified after being supplied
to
> > curry.
>
> Tests show that 'kwargs' is always a new object in the current
> implementation, but I suppose that could change in the future.
>
Yes, my tests also show that curry does not need to make a copy of the
kwargs dict.
> > Also the actual call to the function uses the * and ** operators to
> 'expand'
> > the arguments.
>
> My version would have those too if I had been paying attention while I was
> writing it.
I tested your solution, the cookbook version, and Alex's nested_scopes
version.
All three work properly for the kwd args tests that I performed.
Here is the test script:
It tests only kwd args, not positional args.
I omit the output, but in every case the output matched the expected output.
from __future__ import nested_scopes
# (for Alex's version)
# by Rainer Deyke
class curry_RD:
def __init__(*args, **kwargs):
self = args[0]
self.function = args[1]
self.args = args[2:]
self.kwargs = kwargs
def __call__(self,*args, **kwargs):
kwargs.update(self.kwargs)
return self.function(*(self.args + args), **kwargs)
# by Scott David Daniels (from cookbook)
class curry_CB:
def __init__(self, fun, *args, **kwargs):
self.fun = fun
self.pending = args[:]
self.kwargs = kwargs.copy()
def __call__(self, *args, **kwargs):
if kwargs and self.kwargs:
kw = self.kwargs.copy()
kw.update(kwargs)
else:
kw = kwargs or self.kwargs
return self.fun(*(self.pending + args), **kw)
# by Alex Martelli
# (using nested_scopes)
def curry_AM(func, *args, **kwds):
def callit(*moreargs, **morekwds):
morekwds.update(kwds)
return func(*(moreargs+args), **morekwds)
return callit
curries = {'Cookbook':curry_CB,'Rainer':curry_RD, 'Alex':curry_AM }
def fn(size='small',color='blue',shape='circle'):
return '%s %s %s' % (size,color,shape)
for name in curries.keys():
curry = curries[name]
print
print name
print
f = curry(fn)
print 'expect: small blue circle'
print f()
print
print 'expect big red circle'
f = curry(fn,color='red')
print f(size='big')
print
print 'TEST: nested curries:'
f = curry(fn, shape='square')
f2 = curry(f, size = 'big')
print 'expect big purple square'
print f2(color='purple')
print 'expect big blue square'
print f2()
print
kwargs = {'size':'medium','color':'orange','shape':'oval'}
f = curry(fn,**kwargs)
print 'expect medium orange oval'
print f()
print
# see if we can change a kwd arg after curry...
# ( does curry need to copy kwd dict?)
kwargs['shape']='rectangle'
print 'expect medium orange oval (not rectangle)'
print f()
print
More information about the Python-list
mailing list