Beefy Boxes and Bandwidth Generously Provided by pair Networks
Come for the quick hacks, stay for the epiphanies.
 
PerlMonks  

comment on

( [id://3333]=superdoc: print w/replies, xml ) Need Help??

I've been doing a little research into the strange world of functional programming using Haskell. It's an interesting language and I was playing with it to improve my understanding of how functional programming works with Perl. I feel that I have a fine grasp on map, grep, sort, closures and other aspects of Perl that are related to functional programming. Further, I'm familiar with Why I like Functional Programming by tilly. However, I would love to see more examples of how things are done in a functional manner in Perl. For example, in Perl, to compute the product of all of the elements of a list, we might do the following:

my @list = qw/ 7 5 2 2 /; my $prod = shift @list; $prod *= $_ foreach @list;

In Haskell, this would be illegal because variables are defined, not assigned values. In other words, if you have x = 3, then 'x' is always equal to three. You cannot change the value and last two lines of code above would not have a direct equivalent (shifting an element of off the list changes the list in the second line).

Let's say that I want the first element of a list. The first line below is bad, the second is good.

# bad. Alters @_ sub head { shift } # good. Preserves @_ sub head { $_[0] }

This leads to interesting properties of the language. In the following example, 'i' is set to seven, even though 'j' is not listed yet. This is because these variables are defined at compile time.

i = j + 1 j = 6

Needless to say, a similar construct in Perl would not perform the same. We can think of these variables as being analogous to what we experience in our math classes. If we have x + 3 = 7, we know that x is four and that its value will not change.

Another interesting thing about Haskell is that it does not have loop constructs such as while or for. This is because the language is essentially a series of definitions and the compiler or interpreter applies these definitions to the problem at hand and determines how to arrive at the result. Using loops involves having the programmer direct the actions of the computer and typically uses a variable set as a flag to indicate when the loop terminates. Since you cannot change the value of variables in Haskell, you cannot set such a flag. Thus, loops appear to be replaced with recursive definitions. Let's use this to get the product of a list in Haskell.

prodList lst = if (length lst)==1 then head lst else head lst*(prodList (tail lst))

And here's a Perl equivalent of that.

sub head { $_[0] } sub tail { @_[1..$#_] } sub prod_list { 1 == @_ ? head @_ : (head @_) * prod_list( tail @_ ) }

So in looking at functional programming as a series of definitions and not as a series of directives, we define a factorial function in terms of the &prod_list function.

sub factorial { prod_list( 1 .. $_[0] ) }

This leads to the following program to determine the factorial of a number supplied on the command line.

#!/usr/bin/perl -w use strict; sub head { $_[0] } sub tail { @_[1..$#_] } sub prod_list { 1 == @_ ? head @_ : (head @_) * prod_list( tail @_ ) } sub factorial { prod_list 1 .. $_[0] } print factorial shift;

Yes, it looks very strange. Also, note that for simplicity, I have left off error checking. Further, functional programming as performed by Haskell is difficult to simulate in Perl as Haskell does many interesting tricks with type checking. I also think that my factorial example may not be the best example as that's a fair amount of overhead to set up a simple function (again without error checking).

sub factorial { my $result = 1; $result *= $_ for 1 .. $_[0]; $result }

I realize that I have given some rather simplistic examples above that do not even begin to touch on the power of functional programming, but rather, they illustrate some of the different approach to problem solving. Perhaps a more classic example would appear to be the Schwartzian Transform (ST).

@new_list = map { $_->[0] } sort { $a->[1] <=> $b->[1] } map { [ $_, expensive_func( $_ ) ] } @old_list;

With the ST, we don't have "loops", per se. Instead, we can think of these as definitions of how to transform a list. Further, we don't have the variables being reassigned to (though they might be in &expensive_func).

I am wondering about the following things.

  • What other examples can Monks offer?
  • Has anyone developed any guidelines regarding when such a style might be appropriate in Perl?
  • Do those small functions in the first factorial example pay off if they are to be heavily reused?
  • Can adding the constraint of not altering a variable's value lead to "more correct" code, if done in a non-functional language?
  • Is my brief meditation missing the point of functional programming?

Note that there are many things that I have not touched on. I don't know what monads are, for example. Also, I haven't dicussed guards (which appear to be similar to method overloading), lazy evaluation (hurry up, Perl 6! :), or first class functions, to name just a few topics.

Update:

It should be noted that Perl types being based on data structures as opposed to data types definitely causes potential problems here. Also, the &prod_list could be written differently.

# who says Perl has too much punctuation? :) sub prod_list { 1 == @_ ? $_[0] : $_[0] * prod_list( @_[1..$#_] ) }

Also, much of functional programming involves passing functions to other functions. I haven't discussed that.

This is all a long-winded way of saying "I don't quite grok functional programming."

Cheers,
Ovid

Join the Perlmonks Setiathome Group or just click on the the link and check out our stats.


In reply to When would you use functional programming? by Ovid

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post; it's "PerlMonks-approved HTML":



  • Are you posting in the right place? Check out Where do I post X? to know for sure.
  • Posts may use any of the Perl Monks Approved HTML tags. Currently these include the following:
    <code> <a> <b> <big> <blockquote> <br /> <dd> <dl> <dt> <em> <font> <h1> <h2> <h3> <h4> <h5> <h6> <hr /> <i> <li> <nbsp> <ol> <p> <small> <strike> <strong> <sub> <sup> <table> <td> <th> <tr> <tt> <u> <ul>
  • Snippets of code should be wrapped in <code> tags not <pre> tags. In fact, <pre> tags should generally be avoided. If they must be used, extreme care should be taken to ensure that their contents do not have long lines (<70 chars), in order to prevent horizontal scrolling (and possible janitor intervention).
  • Want more info? How to link or How to display code and escape characters are good places to start.
Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others romping around the Monastery: (3)
As of 2024-04-20 03:02 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found