So I have been hanging out at #perl6 and working with autrijus and the group on PUGS. Mostly I have been writing tests, but recently I decided to whip up some code examples to test my new found perl 6 knowledge.

Now I have always been a fan of functional languages, and one of my favorite features of functional languages is argument pattern matching. So I decided to try and reproduce some of the classic examples of argument pattern matching using the multi-sub feature of perl 6.

Here is the Standard ML code I based these examples off of.

fun sum [ ] = 0 | sum (h::t) = h + (sum t); fun length [ ] = 0 | length (h::t) = 1 + (length t);
And the Perl 6 code ...
multi sub sum () returns Int { 0 } multi sub sum (*$x, *@xs) returns Int { $x + sum(@xs) } multi sub length () returns Int { 0 } multi sub length (*$x, *@xs) returns Int { 1 + length(@xs) }
And the equivalent (sorta) Perl 5 code ...
sub sum { return 0 unless @_; my ($h, @t) = @_; return $h + sum(@t); } sub length { return 0 unless @_; shift; return 1 + length(@_); }
These examples are quite simple, but the full example code has a few more complex examples in it.

I encourage anyone who is doubting the future of perl 6 to download the latest PUGS and give it a try. Even though it is still a little rough around the edges, it is progressing quite nicely and has a number of new and interesting language features already implemented.

And of course we can always use more tests and examples.

-stvn

Replies are listed 'Best First'.
Re: Functional Perl 6/PUGS
by bunnyman (Hermit) on Feb 28, 2005 at 15:08 UTC

    Maybe this is just my procedural background showing, but is it a good idea to use these recursive functions? In Perl 5 this blows the stack when too many arguments are passed. Does this work better in PUGS and the planned Perl 6? I assume this works fine in ML because it is tail-recursive.

      Maybe this is just my procedural background showing, but is it a good idea to use these recursive functions?

      Well, they are examples, and no you probably wouldn't want to actually do a recursive length function (especially since you can just do +@array in perl 6 to get the same thing). But recusion is not the bad thing it used to be back in the days of low CPU/low memory, and even then it was mostly an implementation issue.

      In Perl 5 this blows the stack when too many arguments are passed.

      Perl 5 actually does not have a stack (at least not in the same way that C has a stack). Perl 5 can recurse forever (or until your memory runs out). See this thead for more details.

      I assume this works fine in ML because it is tail-recursive

      Actually neither of those ML functions are tail recursive as both of them force all calculation to be done at the last moment. They could both be optimized to be tail recusive though. And ML's efficiency actually does not come from tail recursion, but from a stackless compilation model (IIRC based on heaps) which is specifically made with recursion in mind (sort of the opposite of C's compilation model).

      Does this work better in PUGS and the planned Perl 6?

      Well PUGS is written in Haskell, which is also a functional language like ML, which handles recursion just fine as well. However, i cannot say if that will actually matter since it matter more how autrijus is writing the interpreter than the language he is using to write it in. However, I assume that recursion will be reasonably efficient in perl 6 (however it is not all that un-efficient in perl 5 though).

      -stvn

      I gotta agree.

      Why count bytes when perl already knows the length of a string?

      Why wait for four billion, two hundred and ninty four million, nine hundred and sixty seven thousand, two hundred and ninty six mutual recursions to find out that 4294967296 is even when this can be determined with a single opcode (usually with an optional branch!) on every processor known to man?

      And how come -1 tests true as both even and odd?

      It kinda like 50 years of programming has been forgotten. Next, they'll be producing a uniq list from a non-unique list by comparing every element in a list against the first element of another list constructed by removing the first element from the first list and then against the next by comparing that element against the first element of a new list constructed from the second list by removing it's first element, and then comparing it against the third element by comparing it against the first element of a new list constructed by removing the first element from the third list and then comparing it with the fourth element by comparing it with the first element of a new list constructed by removing the first element from the fourth list--(Geez! I do hope this list isn't to long!)--and then comparing it against the fifth element of the list by comparing it against the first element of a new list constructed by removing the first element from the fifth list...

      Oh wait! They are!


      Examine what is said, not who speaks.
      Silence betokens consent.
      Love the truth but pardon error.

        FWIW, the code is not meant to be efficient, or real-world useful. It is meant to be an example of the argument pattern matching style of ML with perl6.

        As for "why the hell would anyone program like this" question, the answer is that (virtually) no one really would.

        However, it does illustrate the style of programming which is free of both assignment statements and side effects. This style is an area of interest in the study of concurrent programming (both non-assignment and single assignment variables actually). By not introducing side effects and limiting assignment you can remove an entire class of concurrent programming issues.

        It is also useful to not think of this style of programming the way you view procedural execution. If you were to write these functions in prolog (or something similar like Erlang) the code would be quite similar, but since the execution model is much different, they are not as in-efficient as you might think.

        And if you were stranded on a deserted isle with only functions and simple logical and comparison operators, and all your assignment statements, for & while loops, if statements etc, were lost at sea. You would have to program like this too.

        -stvn
Re: Functional Perl 6/PUGS
by rg0now (Chaplain) on Feb 28, 2005 at 15:53 UTC
    What always makes me sad about functional programming is that, after reading a plethora of tutorials on it (Why I like functional programming, Functional take 2), I still can not train my brain to think in terms of functions instead of objects or other perlish constructs.

    Every now and then I try to solve a problem based on functional programming paradigms (mostly in LISP), but I end up with a mostly Perlish code instead...

    Update: Apparently, BrowserUk pretty much more comprehensibly formulated my problems with functional programming in the above thread... Still I have to learn to word my thoughts better...

    rg0now

        Pardon me if this is offtopic here, but you seem to be much on track with functional programming, so I ask here: do you think that developing macros in Emacs LISP for mostly text-processing kind of problems (like: count the words in a paragraph, capitalize the first letter of all words of the selected region, etc.) is a good way to get on with functional programming? What other problems do you recommend to solve for a newbie? LISP is a must: Pugs just does not seem to be their yet...

        I want to add functional programming to my heavy artillery very badly...:-)

        rg0now