=head1 Some ramblings with Perl6 Ok, I finally re-installed Perl6 and, given it's august, I'll probably try and use it a bit. So I came back to the time when I was learning to program in Pascal, trying to make stupid programs related to prime numbers, and tried to do something similar. =head2 Just to start, give me something! The first issue to solve is to get some input from the user, whatever I want to do with it. A program controlled if some number n was prime, another calculated the n-th prime number, another one the first prime number above a given number n... in any case, we need n. In Perl 5, I'd resort to either the command line, or the standard input, with something along these lines: my $n = shift || <>; In Perl 6 it doesn't seem so straightforward: #!/home/poletti/bin/pugs # vim: filetype=perl : use v6; my $n = shift || <>; say "you requested $n"; (Yes, I use vim :) A nice thing in Perl 6 is that you can I things instead of simply Cing them - this automatically adds a C<\n> at the end of the "sentence". Time to execute: poletti@PolettiX:~/sviluppo/perl/perl6$ pugs primes.pugs *** unexpected "|" expecting term at primes.pugs line 5, column 15 Ouch! I got hit by the C! Time to grep something inside the examples directory, where I find the C example! Ok, before I go on I must confess one thing - instead of my $n = shift || <>; I had originally written: my $n = shift; $n = <> unless defined $n; which is a little cleaner (think of the case of '0' being input) but much much uglier :) I found the one-line idiom in C, anyway. Ok, so F basically translates the one-line into: my $n = @*ARGS[0] || =<>; Ugh! Apart from the fact that this probably won't C anything, it's much more counter-intuitive typing! Wait a minute... this works as well: my $n = @ARGS[0] || =<>; Now is a bit more readable IMHO, even if there is the obvious mentality shift in the sigil and, of course, the change in the name (in Perl 5 this would be spelt C<$ARGV[0]>). But why do they I work?!? What's this asterisk for? An hint from IRC points me towards the Synopses, and in particular in C I find that Perl 6 does not simply have sigils, but has I as well! The asterisk indicates that the ARGS variable to be used is one on the global scope, so here it is! The translator has been semantically more correct (for this aspect), but we're still missing the C: my $n = @*ARGS.shift || =<>; which works as well, and does B what I wrote in Perl 5. I think I'll miss the "defaulting" feature of C (but only for a bit). Now the part after the "||"... why the equal sign? I already know a little bit: the C<< >> syntax is now used as a shortcut for the good ol' C operator, so: my $m = <>; would simply put the empty string into C<$m>! Again in Synopsis 2 I learn that the input is now handled with a single equal sign, like in: for =$handle { ... } but why I need the C<< <> >> is now a mistery... What if it really represents the empty string, as above? Let's try: #!/home/poletti/bin/pugs # vim: filetype=perl : use v6; my $n = @*ARGS.shift || =''; say "you requested $n"; no way: poletti@PolettiX:~/sviluppo/perl/perl6$ pugs primes.pugs *** : openFile: does not exist (No such file or directory) at primes.pugs line 5, column 1-28 But hey! This is no fair substitution at all! Let's try the C operator instead: #!/home/poletti/bin/pugs # vim: filetype=perl : use v6; my $n = @*ARGS.shift || =qw{}; say "you requested $n"; Now it works! Only... why? The docs report that the equal sign in this case acts as some kind of "activator" for what follows, and it probably expects to receive an empty list to think "let's read something". As a matter of fact, this works as well: #!/home/poletti/bin/pugs # vim: filetype=perl : use v6; my $n = @*ARGS.shift || =() ; say "you requested $n"; The bottom line is probably that there is a little "visual" shift from C<< <> >> to C<< =<> >>, so it's probably better to stick to the original translation in this case. =head2 Use the data: evaluate if a number is prime The basic function in all my Pascal trials was, of course, the one that checked from number primeness. And no, I am not going to provide some clever implementation. Let's start with a stub function and a simple message output: #!/home/poletti/bin/pugs # vim: filetype=perl : use v6; my $n = @*ARGS.shift || =<> ; say "$n is ", (is_prime($n) ? '' : 'NOT '), 'prime'; sub is_prime { return 1; } Wow, it blows! Here's the error I got: poletti@PolettiX:~/sviluppo/perl/perl6$ pugs primes.pugs 5 *** unexpected "?" expecting comment, operator or ")" at primes.pugs line 7, column 29 But I know why: the good ol' ternary C has now become C, so the change is straighforward: #!/home/poletti/bin/pugs # vim: filetype=perl : use v6; my $n = @*ARGS.shift || =<> ; say "$n is ", (is_prime($n) ?? '' :: 'NOT '), 'prime'; sub is_prime { return 1; } What the heck! It blows again! poletti@PolettiX:~/sviluppo/perl/perl6$ pugs primes.pugs 5 *** unexpected ":" expecting comment, operator or "!!" at primes.pugs line 7, column 35 This should teach me to B the documentation: the ternary (operator? test?) has now become C, with the exclamation point instead of the colon! Hummm, that beatiful "Periodic Table of Perl 6 Operators" needs some updating, let's see... ok now this works: #!/home/poletti/bin/pugs # vim: filetype=perl : use v6; my $n = @*ARGS.shift || =<> ; say "$n is ", (is_prime($n) ?? '' !! 'NOT '), 'prime'; sub is_prime { return 1; } Incidentally, it's good to see that the good ol' syntax for subroutine declaration and definition is still alive! Let's write the sub, now, starting with the first bits: sub is_prime { my $n = shift; return 0 if $n <= 1; return 1 if $n <= 3; return 1; } Ouch! I got biten by the lonely C again! No defaults, so I promptly correct to: sub is_prime { my $n = shift @_; # Using shift as a function here, not as method. # Just to try it out. return 0 if $n <= 1; return 1 if $n <= 3; return 1; } Good to see the postfix C still working. But in Perl6 there's more for this sub parameters stuff, as audreyt suggested in IRC: sub is_prime ($n) { # Parameters! Arguments! No more "prototypes"! return 0 if $n <= 1; return 1 if $n <= 3; return 1; } It's true, subroutine parameters are fully supported now, a big step from the prototypes available in Perl5. On with the "hard" part, now; again, I'll try to go Perl 5 to start: sub is_prime ($n) { return 0 if $n <= 1; return 1 if $n <= 3; for my $factor (2 .. sqrt($n)) { return 0 unless $n % $factor; } return 1; } No way. Iteration is done differently, but discovering why reveals a lot of interesting things... First of all, I wasn't so distant from something working; had I used the default variable, it would have worked! So: sub is_prime ($n) { return 0 if $n <= 1; return 1 if $n <= 3; for (2 .. sqrt($n)) { return 0 unless $n % $_; } return 1; } works! But C teaches more: the assignment is visually more sweet: sub is_prime ($n) { return 0 if $n <= 1; return 1 if $n <= 3; for (2 .. sqrt($n)) -> $factor { return 0 unless $n % $factor; } return 1; } The final thing that I read from the docs is controversial in my mind: does it clarify something that had remained obscure, or just adds fog in my brain? It turns out that instead of writing: while (<>) { ... } # Perl 5 you'd better write for =<> { ... } # Perl 6 Wow, that C<< =<> >> again! But this is claimed to be short for for =$*ARGS { ... } Oh, my! This is where I appreciate my 33 years: I can stop it here without feeling (too) guilty ;) =head2 A pathetic attempt to conclude Well, Perl 6 seems a lot cool, I've no doubt about this. The "old" code won't work seamlessly, at least not in a C condition, but this was expected given the big changes happening. There are probably things I'll miss, like the defaulting feature of C, but all in all it's not that loss. The documentation is sort-of complete - after all we have Pugs - but rather difficult to navigate and not always "explicit". But I surely didn't expect anything more! Some aspects are still obscure... but I'll leave them for the next time! Last, but not least, here's the final script: #!/home/poletti/bin/pugs # vim: filetype=perl : use v6; my $n = @*ARGS.shift || =<> ; say "$n is ", (is_prime($n) ?? '' !! 'NOT '), 'prime'; sub is_prime ($n) { return 0 if $n <= 1; return 1 if $n <= 3; for (2 .. sqrt($n)) -> $factor { return 0 unless $n % $factor; } return 1; } =cut