Introduction

After reading FoxtrotUniform's excellent node on currying, I've been pondering the differences between a closure and currying a function. I want to try to describe what I see as the differences, thereby exposing myself to the critique of the monastery :)

Anyhow. Given this (toy) closure:

sub toggle { my @states = @_; my $index = 0; return sub { return $states[ $index++ % ( scalar @states ) ]; } }

This little snippet takes a list of arguments and returns a function reference. Calling the reference will return the next element in the argument list. Simple use:

my $t = &toggle qw( alfa beta gamma ); print &$t(), "\n" foreach ( 1 .. 20 );

The point is that @states and $index are unique context to each of the function references, and calling &toggle with different argument lists will give us independent function references that have distinct behaviour.

Now, given this function for currying:

sub curry { my ( $fnc, @arguments ) = @_; return sub { return &$fnc( @arguments, @_ ); } }

And this toy function for echoing the contents of a list.

sub echo { return join( " ", @_ ); }

With currying, we can "prime" &echo with a set of arguments that will be prepended to everything it prints out later:

my $boss = &curry( \&echo, "My", "boss:" ); my $friend = &curry( \&echo, "Johnny:" ); print &$boss qw( has pointy hair ), "\n"; # "My boss: has pointy hair print &$friend qw( likes rock and roll ), "\n"; # etc.

What I'm trying to say

Obviously, both the &toggle closure and the &curry function are implementet in the same way, namely Perl's closures. Why the difference in naming? Why not just talk about functions like &curry as closures?

I think it is a good idea to separate these two concepts, as currying includes a function as an argument. This seems to me to be the key, as a closure in itself is a method for giving a function context (A poor man's object, as some say. Others call objects a poor man's closure.) so each closure is explicitly created and tailored to it's use.

Since currying receives its function from the outside as an argument, it does not care about what it does to whom. This makes it to me a more flexible programming technique, since I don't have to explicitly set up the inner workings of a closure. Borrowing from object oriented terminology, maybe currying can be considered as a kind of closure constructor, or factory?

In closing, I want to stress that this is my understanding of these concepts, and that I've been using the last few days to grasp what it means. If any wiser monks would point out the errors in my argumentation, I'd be more than happy.

pernod
--
Mischief. Mayhem. Soap.

Replies are listed 'Best First'.
Re: Closures versus Currying
by PodMaster (Abbot) on Aug 31, 2004 at 10:00 UTC
    Anyhow. Given this (toy) closure
    That is not a closure. Its a "function generator", it returns closures, but toggle itself is not a closure. perldoc -q closure

    MJD says "you can't just make shit up and expect the computer to know what you mean, retardo!"
    I run a Win32 PPM repository for perl 5.6.x and 5.8.x -- I take requests (README).
    ** The third rule of perl club is a statement of fact: pod is sexy.

      Ah, now I (finally) see the distinction! Thank you for pointing this out for me :)

      pernod
      --
      Mischief. Mayhem. Soap.

Re: Closures versus Currying
by grinder (Bishop) on Aug 31, 2004 at 10:33 UTC

    Just a couple of style issues: if you can't explain precisely why you are using ampersands in your subroutine calls then leave them off (see perlsub if you want to find out more).

    Secondly, since at least perl 5.5.3 (or 5.005_03 if you like), Perl admits a different syntax for calling out coderefs that is considered cleaner. It follows the form $coderef->(). Rewriting your code, we get:

    my $boss = curry( \&echo, "My", "boss:" ); my $friend = curry( \&echo, "Johnny:" ); print $boss->(qw( has pointy hair )), "\n"; # "My boss: has pointy hai +r print $friend->(qw( likes rock and roll )), "\n"; # etc.

    By the way, the code doesn't parse correctly. perl can't determine what the fragment &$friend qw( likes rock and roll ), "\n" is meant to mean. A pair of parentheses are needed.

    - another intruder with the mooring of the heat of the Perl

      (...) if you can't explain precisely why you are using ampersands in your subroutine calls then leave them off (...)

      Because ampersands make it clear to everyone that you know you're using a user-defined function rather than a builtin, and when used with parens don't do anything out of the ordinary (viz. (tye)Re: A question of style)?

      I use ampersands everywhere I call user functions. It fits in nicely with the Perlish idea of "every symbol that isn't part of the language has a glyph" --- actually, now that I type that, I'm not certain that it's true, but it's mostly true so I stand by my coding style. Anyways, as tye points out, ampersands and parens Is Your Friend.

      --
      F o x t r o t U n i f o r m
      Found a typo in this node? /msg me
      % man 3 strfry

        I consider ampersands to be a question of personal taste.

        I only use them when necessary so that my coding style can stay more uniform when I switch languages. YMMV on whether this is good reasoning.

Re: Closures versus Currying
by hardburn (Abbot) on Aug 31, 2004 at 13:03 UTC

    Why not just talk about functions like &curry as closures?

    For language-independance. Closures might be the way curring is implemented in Perl, but that doesn't mean it's always implemented that way.

    For instance, OcaML technically only supports one argument per function. However, the language cheats by recursively passing on the next argument in a multi-arg list and curring all previous arguments. This process is transparent to the programmer (though there are some tricks you can do involving this technique).

    "There is no shame in being self-taught, only in not trying to learn in the first place." -- Atrus, Myst: The Book of D'ni.

Re: Closures versus Currying
by tilly (Archbishop) on Aug 31, 2004 at 15:40 UTC
    I already gave my explanation for why it is good to have specific language for this at Re^6: Specializing Functions with Currying. I also maintain that there is little need to remember the word "curry" if the only language that you ever intend to program in is Perl 5.

      Unless you want to order a spicy dish, of course. ;-)

      Makeshifts last the longest.

        Or if you want to better express your intent to people who know what currying is.

Re: Closures versus Currying
by FoxtrotUniform (Prior) on Aug 31, 2004 at 22:00 UTC

    Closures are (very roughly) functions-with-data, in much the same way that objects are data-with-functions. Currying is the technique of building one function from another, where the new function is a "partially evaluated" version of the old. In Perl5, currying can be implemented with closures; note that there's a lot more that you can do with Perl5-closures than just curry a function. In this case, I think you're comparing apples (Perl5-currying) and fruit (Perl5-closures).

    --
    F o x t r o t U n i f o r m
    Found a typo in this node? /msg me
    % man 3 strfry