fp/lambda question

Alex Martelli aleax at aleax.it
Sat Apr 13 18:22:44 EDT 2002


Jozef wrote:
        ...
>> def relatively_prime(a, b): return gcd(a, b) == 1
> 
> Thats funny, I wanted to do that but I don't know how to use filter with a
> function that takes 2 variables. E.g., to get a list if all numbers less
> than 10 relatively prime to 3, I would write
> 
> filter(relatively_prime, range(1, 10)) # aaah, where does the 3 go???

filter wants a unary function, and, as you saw in Haskell, you do that by 
_currying_ (Haskell Curry is the name of the mathematician who thought
that up...):

> So I learned the lambda way. I also looked at Haskell recently, and  there
> (relatively_prime 3) is a valid function that takes only 1 argument, so no

Python doesn't have built-in curry, so you hack it up in any of several 
ways (of which lambda one), such as a closure:

def relativelyPrimeToN(N):
    def relatively_prime(x, N=N): return gcd(x, N) == 1
    return relatively_prime

and then

filter(relativelyPrimeToN(3), range(1, 10))

curry itself isn't hard to write (see the Python Cookbook for various 
approaches) -- e.g., with nested scopes, and only caring about
positional arguments, again as a closure:

def curry(f, *args):
    def curried(*more_args): return f(*(args+more_args))
    return curried

and then

filter(curry(relatively_prime, 3), range(1, 10))

> problem there. Just a thought: a nice way to get rid of lambda's and save
> a little typing would be if for example
> 
> filter(is_even, alist)
> and
> filter(is_even(_), alist)
> 
> meant the same thing, and in
> 
> filter(relatively_prime(3, _), alist)

Not a chance, IMHO.  _ is a valid Python identifier, used in the 
interactive interpreter (result of the latest expression statement)
and elsewhere (e.g. the gettext module).

If "currying with different patterns of supplied/nonsupplied args"
was crucial (but Haskell doesn't have it... you have to define a
named function for that), you could, I guess, use some other
place-holder object -- but not, I think, with function-call syntax,
or you could never pass that place-holder to any function.
Something like curry(relatively_prime, 3, curry_arg) -- though
here it would have no added value wrt the simpler curry I suggest.


Alex




More information about the Python-list mailing list