The Beauty of Perl 6 Parameter Passing
by Phil CrowMarch 01, 2007
Of course, Pugs is not finished. It couldn't be. The Perl 6 design is still in progress. However, Pugs still has many key features that are going to turn our favorite language into something even greater.
A Simple Script
I'm about to take a big risk. I'm going to show you a script that performs Newton's method. Please don't give up before you get started.
Sir Isaac Newton was a noted computer scientist and sometime astronomer, physicist, and mathematician, as the communications of the ACM once described him. He and others developed a fairly simple way of finding square roots. It goes like this:
#!/usr/bin/pugs
use v6;
my Num $target = 9;
my Num $guess = $target;
while (abs( $guess**2 - $target ) > 0.005) {
$guess += ( $target - $guess**2 ) / ( 2 * $guess );
say $guess;
}
This version always finds the square root of 9, which conveniently is 3. This aids testing because I don't have to remember a more interesting square root, for example, the square root of 2. When I run this, the output is:
5
3.4
3.0235294117647058823529411764705882352941
3.0000915541313801785305561913481345845731
The last number is the square root of 9 accurate to three decimal places.
Here's what's going on.
Once Pugs is installed, you can use it in a shebang line (on Unix or Cygwin, at least). Otherwise, invoke the script through pugs as you would for perl:
$ pugs newton
To let Perl 6 know that I want Perl 6 and not Perl 5, I type use v6;.
In Perl 6, the basic primitive types are still scalar, array, and hash. There are also more types of scalars. In this case, I'm using the floating-point type Num for both the target (the number whose square root I want) and the guess (which I hope will improve until it is the square root of the target). I can use this syntax in Perl 5. In Perl 6 it will be the norm (or so I hope). I've used my to limit the scope of the variables just as in Perl 5.
Newton's method always needs a guess. Without explaining, I'll say that for square roots the guess makes little difference. To make it easy, I guessed the number itself. Obviously, that's not a good guess, but it works eventually.
The while loop goes until the square of the guess is close to the target. How close is up to me. I chose .005 to give about three places of accuracy.
Inside the loop, the code improves the guess at each step using Newton's formula. I won't explain it at all. (I've resisted the strong temptation from my math-teacher days to explain a lot more. Be glad I resisted. But if you are curious, consult a calculus textbook. Or better yet, send me email. I'd love to say more!) I'll present a more general form of the method soon, which may jog the memories of the calculus lovers in the audience, or not.
Finally, at the end of each iteration, I used say to print the answer. This beats writing: print "$guess\n";.
Except for using say and declaring the type of the numbers to be Num, there's not much to separate the above script from one I might have written in Perl 5. That's okay. It's about to get more Perl 6ish.
An Exporting Module
While it's fine to have a script that finds square roots, it would be better to generalize this in a couple of ways. One good change is to make it a module so that others can share it. Another is to turn loose the power of Newton and look for other kinds of roots, like cube roots and other even more exotic ones.
First, I'll turn the script above into a module that exports a newton sub. Then, I'll tackle generalizing the method.
When I'm finished, I want to be able to use the module like this:
#!/usr/bin/pugs
use Newton;
my $answer = newton(4);
say $answer;
Because say is so helpful, I could combine the last two statements:
say "{ newton(4) }";
That's right, strings will run code if you put it in braces.
The module, Newton.pm, looks like this:
package Newton;
use v6;
sub newton(Num $target) is export {
my Num $guess = $target;
while (abs( $guess**2 - $target ) > 0.005) {
$guess += ( $target - $guess**2 ) / ( 2 * $guess );
}
return $guess;
}
Here begins the familiar package declaration borrowed from Perl 5. (In Perl
6 itself, package identifies Perl 5 source code. The v6 module lets you run some Perl 6 code
in Perl 5 programs.) Immediately following is use v6;, just as in
the original script.
Declaring subs in Perl 6 doesn't have to be any different than in Perl 5, but it should be. This one says it takes a numeric variable called target. Such genuine prototypes allow for Perl 6 to report compilation errors when you call a sub with the wrong arguments. That single step will move Perl 6 onto the list of possible languages for a lot of large-scale application development shops.
At the end of the declaration, just before the opening brace for the body, I included is export. This puts newton into the namespace of whoever uses the module (at least, if they use the module in the normal way; they could explicitly decline to take imports). There is no need to explicitly use Exporter and set up @EXPORT or its friends.
The rest of the code is the same, except that it returns the answer and no longer proclaims its guess at each iteration.
Pages: 1, 2 |

