Beefy Boxes and Bandwidth Generously Provided by pair Networks
Syntactic Confectionery Delight
 
PerlMonks  

Re^3: Near-free function currying in Perl

by dragonchild (Archbishop)
on Nov 17, 2004 at 15:19 UTC ( #408437=note: print w/replies, xml ) Need Help??


in reply to Re^2: Near-free function currying in Perl
in thread Near-free function currying in Perl

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? For example:
sub foo ($$;$) { ... } my $curried_foo = foo( 1 ); my $return_value = foo( 1, 2 );

I'm thinking a source filter would be needed to convert

sub foo ($$;$) { ... } to sub foo { if (@_ < 2) { my $arg = shift; return sub { foo($arg, @_) }; } ... }
Wouldn't that work?

Being right, does not endow the right to be rude; politeness costs nothing.
Being unknowing, is not the same as being stupid.
Expressing a contrary opinion, whether to the individual or the group, is more often a sign of deeper thought than of cantankerous belligerence.
Do not mistake your goals as the only goals; your opinion as the only opinion; your confidence as correctness. Saying you know better is not the same as explaining you know better.

Replies are listed 'Best First'.
Re^4: Near-free function currying in Perl
by tmoertel (Chaplain) on Nov 17, 2004 at 17:23 UTC

    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

      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.

      -stvn
        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

Re^4: Near-free function currying in Perl
by stvn (Monsignor) on Nov 17, 2004 at 15:45 UTC

    My experience with function attributes is limited but what about something like this:

    sub foo ($$$) : curry { ... }
    or if the prototypes and attributes dont get along as they should.
    sub foo : curry($$$) { ... }
    That would be my prefered notation, it is was possible.

    -stvn
      I like
      sub foo : required($$$) { ... }

      That allows more than just currying to use the attribute. Also, you can then do something like:

      sub foo : required( address, city, state, zip ) { ... }

      That way, you can do both parameter validation and named-parameter currying (as per Limbic~Region's comment below). Plus, you're specifying the API, which would allow for something like doxygen to document your API.

      An even nicer thing would be to combine this idea of a required() attribute to methods, meaning that you could do something like:

      package Foo; sub new : required( attr1, attr2 ) : optional( attr3 ) { ... }

      This would behave like Class::MethodMaker and create the attr1(), attr2(), and attr3() mutators, plus require that the first two be passed in to the constructor.

      It wouldn't be too hard to come up with a list of useful function/method attributes. Off the top of my head, I can see multiple uses for:

      • required
      • optional
      • deprecated

      Being right, does not endow the right to be rude; politeness costs nothing.
      Being unknowing, is not the same as being stupid.
      Expressing a contrary opinion, whether to the individual or the group, is more often a sign of deeper thought than of cantankerous belligerence.
      Do not mistake your goals as the only goals; your opinion as the only opinion; your confidence as correctness. Saying you know better is not the same as explaining you know better.

        Maybe we can expand it to work with optional parameters and named parameters ... *ponders* It's very similar to what I posted below. Hrmm ... maybe we can come up with a spec that would meet everyone's needs?

        Being right, does not endow the right to be rude; politeness costs nothing.
        Being unknowing, is not the same as being stupid.
        Expressing a contrary opinion, whether to the individual or the group, is more often a sign of deeper thought than of cantankerous belligerence.
        Do not mistake your goals as the only goals; your opinion as the only opinion; your confidence as correctness. Saying you know better is not the same as explaining you know better.

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: note [id://408437]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others imbibing at the Monastery: (7)
As of 2020-11-24 20:56 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found

    Notices?