brian has been a Perl user since 1994. He is founder of the first Perl Users Group, NY.pm, and Perl Mongers, the Perl advocacy organization. He has been teaching Perl through Stonehenge Consulting for the past five years, and has been a featured speaker at The Perl Conference, Perl University, YAPC, COMDEX, and Builder.com. Contact brian at [email protected].
During the last Perl Whirl Geekcruise (http://www.geekcruise.com), I got to sit in on a Perl 6 talk by Allison Randal. Larry Wall was in the audience too, so often the talk would disgress, in a really interesting way, to what Perl 6 should do in a particular case. Most of the time, Allison wrote a Perl 6 script she sent through Pugs to see what it did do. That is, Perl 6 was out of the realm of theoretical and into the realm of "Let's see what happens."
Pugs (http://www.pugscode.org/) is the "Perl6 Users Golfing System" that Autrijus Tang started in early 2005 as a hobby project and later turned into a full-fledged reference implementation of Perl 6. Its been so successful that the thinkers behind Perl 6 use it to figure out what to do. The speed of development has been blistering, with both Perl and Haskell hackers getting in on the action.
Autrijus selected Haskell, a functional programming language, as the underpinnings for Pugs. He's not aiming to make it into the final Perl 6 interpreter (which will be in Perl 6 itself), but until that's available, Pugs is what we have, and its what you can play with today to write real Perl 6 programs.
So let's write some Perl 6 code. I'll need Pugs, so I need to get that. The first thing I need is the Glasgow Haskell Compiler (GHC). Debian, Gentoo, FreeBSD and probably other popular systems have a "pugs" port. On Windows, you can get the PxPerl binaries. On Mac OS X, my platform of choice, it is a bit more involved. I won't make you sit through details since "How to Install Pugs on Mac OS X 10.4 in 22 Easy Steps" (http://christian.web42.com/en/archives/000023.html) un-ironically tells you how to do just that. If you read that first, you can finish this article while everything is still compiling. In fact, if you don't have everything already installed, I suggest you start the process before you go to bed. By the time you wake up, the compilation of the various pieces should almost be done.
Now that I have everything set up, I want to run the first program I make in any langauge to test that everything runs. Just like in Perl 5, programs are just text files. I create my first Perl 6 program:
#!env pugs say "Hello World";
I run that like any other program. In Perl 6, say()
replaces print()
with
the added bonus of adding a newline for me.
$ ./hello.p6 Hello World
But that's not enough for me. Perl 6 is supposed to make everything an object, so I should get the same warm fuzzies that Smalltalk and Ruby give me. Let's see if I can treat a literal string as an object (which you can't do in Java, for instance, because it's not an object language). Perl 6 also replaces the arrow method call with the dot method call.
#!env pugs "Hello World".say
And it works! I get the same output that I got before. Let's take it a bit further. I want to split the string into characters, join the characters with colons, and print the result. I can do that with a method chain.
#!env pugs "Hello World".split('').join(':').say
I run this program like I did before and get the output that I expect. This is definitely cool.
$ pugs hello3.p6 H:e:l:l:o: :W:o:r:l:d
Perl 6 has some new operators, so I want to give those a try too. The
string concatenation operator found itself all of a sudden without a
character when the dot moved over to the object side of the house, so
Perl 6 pressed into service the tilde, ~
, which was feeling a bit
underused.
#!env pugs say "Hello" ~ " " ~ "World";
I can also write that in the more direct form.
#!env pugs ("Hello" ~ " " ~ "World").say
How about some of the nifty new Perl 6 features? How do those work? I'm especially interested in the hyper-operators that can work with two lists at the same time.
#!env pugs my @one = 1..5; my @two = 8 xx 5; my @sum = @one >>+<< @two; @sum.join( ', ' ).say;
In this program, I declare the array @one
and assign it the range of 1 to
5. That's the same thing in Perl 5. I don't have to use strict
because its on by default. That's why I also lexically declare
the variables: pugs complains otherwise. Next, I use the new xx
operator. That's like the old x
operator, although it explicitly
replicates lists, so pugs doesn't have to figure it out based on context.
Next comes the line with @sum
. On the right hand side, I use the
>>+<<
hyper-operator with arrays on either side of it. It takes the
first thing from the first list and the the first thing from the second
list and performs the operation in the middle, in this case the addition.
That becomes the first element of the output. Then it does it for the
second items, and so on. That's a lot easier than the equivalent Perl 5
map
, and much shorter than writing a loop to do it. Once I have
the sums in @sums
, I join them and send that string to the output.
$ pugs add_lists.p6 9, 10, 11, 12, 13
Another feature I'm looking forward to are junctions. I think of these
as comparison operators from a much more intelligent universe. In reality,
they are from Damian Conway (see Quantum::Superpositions
for the Perl 5),
so its virtually from a much more intelligent universe.
#!env pugs my $num = @ARGS[0]; my @nums = 5 .. 9; if( $num == any( @nums ) ) { "$num is in @nums[]".say } else { "$num is not in @nums[]".say }
I take the first argument from the command line arguments special array,
which is now @ARGS
. I also keep the @
sigil even though I'm asking
for a single element of the array. In Perl 6, I know I have an array
when I see that @
. It doesn't change depending on what I'm doing.
In the if()
, I compare the value in $num
to the any
junction. If the value in $num
is in, well, any of the
values I gave to any
, the result is true. No matter which way the
statement branches, I print (um, I say) a message. Inside the string, I
have to use the empty brackets, []
, to get the array to interpolate.
Without anything between the brackets I get the whole array. That's kind
of annoying right now, but I think I'll like that after a while once I
have to start putting unescaped e-mail addresses into strings.
Along with that, Perl 6 has another nifty, ternary comparison operator. Ever since I've been programming (and that's really not all that long compared to most of you, probably, so that makes it even worse), I've wondered why I had to do two separate comparisons to discover if a value was between two others. In Perl 6 I do it all at once.
#!env pugs if( 5 < @ARGS[0] < 10 ) { "@ARGS[0] is between 5 and 10".say } else { "@ARGS[0] is not between 5 and 10".say }
I run this for a few values and it just works.
$ pugs between.p6 4 4 is not between 5 and 10 $ pugs between.p6 6 6 is between 5 and 10 $ pugs between.p6 5 5 is not between 5 and 10
I'll give you one more example, and then you have to go out on your own. I thought about stopping the article here, and that would have been easy, but there is at least one more operater that I'm going to like using.
Let's say that I want to give my previous program a default value if I did not give a value on the command line. Let me show you how annoying that is in Perl 5, just to remind you:
my $num = defined $ARGV[0] ? $ARGV[0] : "default";
I have to test for definedness because 0
might be a valid value, although
its a value for boolean tests. Perl 6 introduces the //
operator that's a
short circuit operator testing for definedness instead of truth.
my $num = @ARGS[0] // 'default';
I use that in my last comparison program.
#!env pugs my $num = @ARGS[0] // 7; if( 5 < $num < 10 ) { "$num is between 5 and 10".say } else { "$num is not between 5 and 10".say }
When I give this program some arguments, it acts just like before. When I give it 0, it doesn't choose the default value, but when I don't give it an argument, it properly selects the default argument.
$ pugs between2.p6 8 8 is between 5 and 10 $ pugs between2.p6 0 0 is not between 5 and 10 $ pugs between2.p6 7 is between 5 and 10
That's it. You can start using Perl 6 now. You probably don't want to build a business around it or trust millions of dollars to what it might do, but you can start learning it. Pugs has most of Perl 6 implemented in some fashion, and if you find something that's not done, just wait a couple of days.
TPJ