Functional Programming
Giorgi Lekishvili
gleki at gol.ge
Mon Dec 30 11:07:02 EST 2002
Recently I have started on working to make something akin of list presentation of functions, sort of
a lisp way... (well, I well maybe reinventing a bike, but I am doing that stuff just for fun)
That's not difficult, as one can make
class CallableList ( UserList )
and then define __call__ .
However, to have a chance of symbolic programming
(lisp: ( + 'a 3) must yield another list (+ a 3))
would certainly be nice. Is it impossible in Python in principle? For I have had no idea of how to
do it. But lack of my knowledge is no argument, is it?:))
Grtz,
Giorgi
Bengt Richter wrote:
> On 29 Dec 2002 21:51:24 -0600, Mike Meyer <mwm at mired.org> wrote:
>
> >"Martin v. Löwis" <martin at v.loewis.de> writes:
> >
> >> beno wrote:
> >> > Does anyone know of good sources of info for programming using the
> >> > principles of functional programming in Python? Or, to what
> >> > languages is Haskell similar? Any other advice on the subject
> >> > equally welcomed!
> >> - Currying (creating a function from another function by passing some
> >> arguments): This is not directly available in Python; you can often
> >> emulate it with lambda expressions.
> >
> >You don't need lambdas, and you can even make the programmer API look
> >the same. For example:
> >
> >>>> inc = curry(int.__add__, 1)
> >>>> inc(3)
> >4
> >>>> inc(10)
> >11
> >
> >The definition of curry is:
> >
> >class curry:
> > def __init__(self, func, *fixed_args):
> > self.func = func
> > self.fixed_args = fixed_args
> self.__name__ = '<curried %s>' % func.__name__
> >
> > def __call__(self, *variable_args):
> > return apply(self.func, self.fixed_args + variable_args)
> >
> >This idiom is where my python enlightenment began.
> >
> That is a cool class. I added the line to give the result a name, so my timing harness
> could show it in the comparison of:
>
> curryinc = curry(int.__add__, 1)
> and
> fasterinc = int.__add__.__get__(1)
>
> Which shows that (as I'm sure is no surprise to you, but might be worth mentioning) you pay
> a pretty steep price in performance vs something close to optimum.
>
> BTW, I'm not sure the fasterinc way of doing what I did is going to be an ongoing feature,
> so I'm not recommending it. But it seems like nice enough a way to generate an efficient
> function-arg pair that acts like a bound method but which isn't, so maybe either it should
> be blessed or some sanctioned version should be available? I just used it because it's
> something fast to compare with. The name shows up as __add__.
>
> [ 7:21] C:\pywk\clp\curry>timefuns timecurry -c fasterinc -i 1 -c curryinc -i 1 -n 100000
> timing oh: 0.000013 ratio
> __add__: 0.000004 1.00
> <curried __add__>: 0.000047 12.13
>
> [ 7:22] C:\pywk\clp\curry>timefuns timecurry -c fasterinc -i 1 -c curryinc -i 1 -n 100000
> timing oh: 0.000013 ratio
> __add__: 0.000004 1.00
> <curried __add__>: 0.000047 13.12
>
> 12 or 13 times slower is pretty heavy. Of course it's very general. But a function factory
> version seems to be about twice as fast (warning not tested beyond here ;-), e.g.:
>
> def curryfun(func, *fixed_args):
> curriedname = 'curried_f_%s' % func.__name__
> exec """\
> def %s(*variable_args):
> return func(*(fixed_args+variable_args))
> """ % curriedname in vars()
> return vars()[curriedname]
>
> [ 7:30] C:\pywk\clp\curry>timefuns timecurry -c fasterinc -i 1 -c curryinc -i 1 -c curryinc_f
> -i 1 -n 100000
> timing oh: 0.000012 ratio
> __add__: 0.000004 1.00
> <curried __add__>: 0.000047 13.06
> curried_f___add__: 0.000025 6.83
>
> Don't know if Dr. Who is relevantly cooking in India ;-)
>
> Regards,
> Bengt Richter
More information about the Python-list
mailing list