in reply to Re^3: Near-free function currying in Perl in thread Near-free function currying in Perl
This is a good question:
Just out of curiousity, is it because standard Perl
functions do not specify how many parameters they need at a minimum,
so the compiler cannot tell if a function is satisfied? Because, if it
is, couldn't we just use prototypes?
The reason that my "currying" doesn't do real currying isn't
so much because it's a technical challenge but because real currying
doesn't mesh with Perl's (powerful and cool) calling semantics.
Let me explain why I don't like real currying in Perl (5).
First, and most important, it requires a programmer to make a
design-time decision to support currying. Currying hits its stride
only when it is pervasive, and I don't want to limit its use to the
functions that have been made "curry ready" ahead of time by having
been anointed with the right prototypes or annotations. I want to be able to use currying with existing code bases.
Second, there are many useful Perl functions for which we don't
have any way to differentiate among arguments. What is "curriable"
for these functions is solely at the discretion of the caller. I want
a currying solution that works well for these functions, too.
Third, I think that currying is best when it is free. Having
to make annotations just raises its cost. In languages where
you already must make such annotations, the currying comes
at no additional charge. But for Perl, the charge isn't
necessary and (as I have argued above) doesn't buy us much.
Ultimately, I'm not concerned that we don't have "real"
currying. I would rather we have a useful currying-like
concept that makes sense for Perl.
Thanks for the question!
Cheers, Tom
Re^5: Near-free function currying in Perl
by stvn (Monsignor) on Nov 17, 2004 at 18:14 UTC
|
First, and most important, it requires a programmer to make a design-time decision to support currying. Currying hits its stride only when it is pervasive, and I don't want to limit its use to the functions that have been made "curry ready" ahead of time by having been anointed with the right prototypes of annotations.
I agree somewhat with this point. I think that pervasive currying (as you put it) is very useful only in some cases, but can wreak uncontrolled havoc in others (okay maybe not that bad). For instance, your technique would not work with OO, since the $self value cannot be known when you curry your function. And while most people don't think of currying and OO as going together, nothing could be further from the truth. IMO it can be used a very clean type of closure where the $self instance can not only carry data, but behavior as well. I use this technique myself.
I also take issue with the idea that there is something wrong with design-time descisions to support currying. Sure, in some cases you will want to curry a non-designed-for-currying function, but a designed-for-currying-function has the potential to be far superior. I would even argue (somewhat weakly) that a good functional programmer always designs for currying.
| [reply] [d/l] [select] |
|
stvn, thanks for your comments. Let me address this one, in particular:
For instance, your technique would not work with
OO, ...
Why not? For example, here I use currying to pre-bind a method to
a particular object instance:
#!/usr/bin/perl
package MyObj;
use warnings;
use strict;
use AutoCurry ':all';
sub new {
my $self = shift;
my $name = shift;
bless [$name, { @_ }], $self;
}
sub speak_keyvals {
my ($name, $hash) = @{shift()};
print "$name sez: @{[ @$hash{@_} ]}", $/;
}
my $foo = new MyObj( "foo", a => "alpha", b => "beta" );
$foo->speak_keyvals( "a" );
# foo sez: alpha
# for the next line, recall that $o->f(...) === f($o, ...)
my $foo_speaker = $foo->speak_keyvals_c(); # binds to $foo
$foo_speaker->("b");
# foo sez: beta
$foo_speaker->(@$_) for ["a"], ["b"], ["a", "b"];
# foo sez: alpha
# foo sez: beta
# foo sez: alpha beta
Also, regarding this:
I also take issue with the idea that there is something wrong with design-time decisions to support currying.
To clarify, I didn't say that there was anything wrong with
design-time consideration of currying. What I said was that it was a
bad idea to require design-time considerations in order to
make a currying scheme work. With such a requirement, the vast
existing wealth of CPAN is placed beyond the reach of currying.
I don't want my ability to use currying to be dependent upon
somebody else having designed it into the code I'm using. I
want to be able to take old, existing code and curry it, as is.
Cheers, Tom
| [reply] [d/l] |
|
Why not? For example, here I use currying to pre-bind a method to a particular object instance:
I stand corrected. Very nice example.
To clarify, I didn't say that there was anything wrong with design-time consideration of currying. What I said was that it was a bad idea to require design-time considerations in order to make a currying scheme work. With such a requirement, the vast existing wealth of CPAN is placed beyond the reach of currying.
I don't want my ability to use currying to be dependent upon somebody else having designed it into the code I'm using. I want to be able to take old, existing code and curry it, as is.
I agree that it can be nice to not have to require design time considerations for currying to work in many cases. Although I think saying that the all of CPAN is now your curried oyster is maybe a little presumptious. For instance, any function which makes use of caller may or may not work properly, and stack traces will quite possibly get very messy. There is a lot of crazy code on CPAN (and not just TheDamians) and I would guess that some of it would not respond well to currying.
I guess my point really is that currying is something which is not to be used lightly. It is, by its very nature, an advanced technique which is not easily accessible or understandable to most programmers who were trained in procedural or OO programming. A well crafted Haskell or Standard ML function will be built with the understanding, that it will almost certainly be curried at some point. Old perl code will almost certainly not be built with the same considerations. That is not to say that you shouldn't still use currying in those situtations, but I think it ill advised to imply that currying can breath new life into old code.
| [reply] [d/l] |
|
|
|
|
|
|
|