=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<say> things
instead of simply C<print>ing 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<shift>! Time to grep something inside the examples
directory, where I find the C<matrix.p[56]> 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<matrix.p5>, anyway.

Ok, so F<matrix.p6> basically translates the one-line into:

   my $n = @*ARGS[0] || =<>;

Ugh! Apart from the fact that this probably won't C<shift> 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<both> work?!? What's this asterisk for? An hint from IRC points me
towards the Synopses, and in particular in
C<Synopsis 2: Bits and Pieces> I find that Perl 6 does not simply have
sigils, but has I<twigils> 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<shift>:

   my $n = @*ARGS.shift || =<>;

which works as well, and does B<exactly> what I wrote in Perl 5. I think I'll
miss the "defaulting" feature of C<shift> (but only for a bit).
   
Now the part after the "||"... why the equal sign? I already know a little
bit: the C<< <whatever you put here> >> syntax is now used as a shortcut
for the good ol' C<qw> 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<qw> 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<read> 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<shift> 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<if> 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<Synopsis 4: Blocks and Statements> 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<use v6;> condition, but this was
expected given the big changes happening. There are probably things I'll
miss, like the defaulting feature of C<shift>, 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
