Categories

Posts in this category

Wed, 25 Aug 2010

Pascal's Triangle in Perl 6


Permanent link

Today on IRC, Larry Wall showed this piece of Perl 6 code, which he wrote for Rosetta Code:

sub pascal { [1], -> @p { [0, @p Z+ @p, 0] } ... * };
say pascal[^10].perl
# output (reformatted for easy readbility):
# ([1],
#  [1, 1],
#  [1, 2, 1],
#  [1, 3, 3, 1],
#  [1, 4, 6, 4, 1],
#  [1, 5, 10, 10, 5, 1],
#  [1, 6, 15, 20, 15, 6, 1],
#  [1, 7, 21, 35, 35, 21, 7, 1],
#  [1, 8, 28, 56, 70, 56, 28, 8, 1],
#  [1, 9, 36, 84, 126, 126, 84, 36, 9, 1])

That's Pascal's triangle, generated in one line of Perl 6.

The ... is the series operator, which generates lists by feeding the previous value(s) (here always one array) to the generating block on its left, until it reaches the goal on the right (in this case "whatever", which means it returns a lazy, infinite list).

So for example if the previous item was the array [1, 2, 1], the code block evaluates 0, 1, 2, 1 Z+ 1, 2, 1, 0.

Z is the zip operator, Z+ is pairwise addition (ie adding the pairs that the zip operator produced). In our example that leads to 0+1, 1+2, 2+1, 1+0 or 1, 3, 3, 1.

It takes a while to get used to the meta operators and the series operator, but once you've understood them, you can do pretty neat things with them.

[/perl-6] Permanent link

Comments / Trackbacks:

Trackback URL: /blog-en/perl-6/pascal-triangle.trackback

Passerby wrote


Taking advantage of list flattening and zip-adding is very cool!
Can you explain the syntax around the "], -> @p {" part?
I'm guessing that the inner {} is the codeblock which gets repeated until the whatever is met... I don't understand why there is a comma after the [1]. Why are the lists surrounded by square brackets instead of angle brackets?

Moritz wrote

More explanations
The -> @p is the signature of the block; it could have been written as
sub (@p) { [0, @p Z+ @p, 0] }
instead.

The [1] constructs an array which contains one element (the integer 1). The square brackets tell you that the arrays don't flatten in list context.

The general syntax of the series operator is
defaults, block ... limit

So [1] is the first element, and is passed to block to generate the second element (which again is an array), that second element is again passed to the block etc.

Brad Andersen wrote


This is totally unreadable code. No one, not even Saint Larry, should code like this. EVER.

ilmari wrote


Couldn't the block also be written { [ 0, @^a Z+ @^a, 0 ] } to avoid the ugly (in this context) arrow?

Markus Mayr wrote


The code is very readable in my opinion. Usually, only a few people think about the problem in this way, at first. But once you verified that the list approach does the right thing, this is probably the most beautiful code you can get for this problem.

Maybe the Haskell version is even a little bit more beautiful, the -> arrow is still counter-intuitive for me in some cases.

Moritz wrote

Block signatures
@ilmari,

yes, { [ 0, @^a Z+ @^a, 0 ] } also works. In fact you can drop the second ^ if you feel like golfing (the first usage declares the variable without twigil too).

Caleb Cushing ( xenoterracide ) wrote

yada yada
... is the series operator... well that will be confusing since it's the yada yada operator in perl5 it's not like I don't mind some syntactical changes...

Nilson Santos Figueiredo Junior wrote


This is a cool example. It's easy to see the influence of Haskell developers on Perl 6.

Of course, I don't think this will help with Perl 6's popularity at all, as most people can't understand functional programs.

Hercynium wrote


@Brad: It's too bad you think that. I've only followed P6 in a fairly cursory way but that code seems to be quite clear, and impressive in its concision!

Cody Fendant wrote

Gaol?
I think you'll find the code is progressing toward a GOAL, not a GAOL.

Although Brad does seem to want to throw Larry in prison...

not good wrote

It went too far
I think Perl6 will be an over-complicated , syntax-inefficient language.
When I see this my brain tends to fall from my head.
The main idea of Perl really went too far..
That's not what elegance means anymore, it's completely cryptic.

adam_boyers wrote


I can understand why people would call this code unreadable, but I think you need to realize that the code is all new syntactic constructs (except for sub { }). Once you take a little time to understand these constructs, then the code is very readable. And we can't expect people to learn an innovative language without having to learn any syntax, right?

awwaiid wrote


What does pascal[^10] mean (in the second line of your 1-line example)?

TimToady wrote


It means the same as pascal()[0..9], without the clutter.

awwaiid wrote


Ah... I was confused. I somehow began to believe that the [^10] was a very strange reduce operator.... I understood that ^10 is 0..9, but not how [0..9] could be a reduce. But what you mean now :)

awwaiid wrote


... er, I understand what you mean now.

And how in the world did you even know that I asked a question here? You feel a disturbance in the force or something? :)

Write a comment

The comments on this blog post have been disabled; the comment form below will not work.

 
Name:
URL: [http://www.example.com/] (optional)
Title: (optional)
Comments:
Save my Name and URL/Email for next time