Self-currying functions

Dave Benjamin ramen at lackingtalent.com
Fri May 30 15:06:53 EDT 2003


In article <3ecff6e8$1 at nntp0.pdx.net>, Scott David Daniels wrote:
> Dave Benjamin wrote:
> 
>> ...
>> The following is my response, adapted from your example to support Alex
>> Martelli's curry function (and as a result, curried named parameters). I'm
>> starting to find interesting uses I hadn't anticipated.
> > ...
> I am curious why you would want this ability (as opposed to the curry
> interface I provided in the recipe).  In particular, it seems to me
> that there is a difference between a function with zero arguments and
> the result of that function.  In a side-effect free world (which I'd
> argue rarely exists), this might be ok.  Python is cetainly not that
> world.  I expect code would know when it expected a result from a call.
> If this producing a result on no args left is reasonable, what about
> these:
> 
>      Shouldn't selfcurry(lambda:1) == 1?

I'm not sure that I understand your comments. The point of selfcurry is to
modify the behavior of an existing function of two or more arguments so that
they do not need to be supplied at once. A function of zero or one arguments
does not need to be curried. Maybe selfcurry should just give you back your
function, unmodified, in that case.

I don't see what this specific construct has to do with side effects,
besides the obvious connection with functional programming. Whether or not
Python is (or should be) a "side-effect free world" is another conversation
entirely.

> The keyword args seems to interfere with this flavor of currying,
> perhaps you need to add in len(kwargs) to decide on provided arguments.
> 
>      Assuming f = selfcurry(lambda w, x, *y, **z: (w, x, y, z))
> 
>      Is your code correct on:
> 	f(2, x=5)
>      Also consider:
> 	f(w=1, x=2)
>      And consider:
> 	f(w=1)

This is definitely a gray area that I had not thought of. I will try to
explain my reasoning, but I'm open to suggestions. To me, it seems that
keyword arguments behave like options. Just because you make a function
self-currying doesn't mean you want all of its options to suddenly become
required.

What would be the point of explicitly naming positional parameters? The only
advantage I see would be out-of-order evaluation, but if you write functions
whose positional parameters are ordered from the general to the specific,
you expect them to come in that order. Just not all at once.

You would write the above examples as:

f(2)(5)
f(1)(2)
f(1)

Granted, it starts to behave a bit weird when you explicitly name the
positional parameters, and perhaps the selfcurry function could be modified
to be aware of this anomaly, but why would you want to do this in the first
place? Do you normally name your positional arguments explicitly?

> I am curious why you prefer the selfcurry interface (even assuming
> keyword issues are dealt with).  It seems to to violate "explicit
> is better than implicit."

Can you elaborate on that? First of all, I don't think it's a hard and fast
rule. For instance:

for line in file('ramen.txt'):
    print line
    
Is *implicitly* creating an iterator and invoking its next() function on
every iteration to split the file into individual lines. Why not explicitly
create the iterator that explicitly splits on newlines? Because it's
convenient.

Why don't we have to type our variables? Should't we say "list x = []"?
Wouldn't that be more explicit?

I am not advocating that everybody write functions that curry their own
arguments, or that we throw away the ability to name positional parameters
when calling functions. I'd just like the ability to write functions that
have this behavior, and now I have it, and I'm pretty happy about it. =)

Thanks,
Dave




More information about the Python-list mailing list