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