``````=pod

Magazine_Article_06 - The Beauty of Perl 6 Parameter Passing

Phil Crow L<philcrow2000@yahoo.com>

Its published March 01, 2007 on perl.com and not changed since.
Find the original under:

L<http://www.perl.com/pub/a/2007/03/01/perl-6-parameter-passing.html>

Perl 6 is not finished, but you can already play with it. I hope this
article will encourage you to try it. Begin by installing Pugs
(L<http://search.cpan.org/perldoc?pugs>), a Perl 6 compiler implemented
in Haskell. Note that you will also need Haskell (see directions in the
Pugs F<INSTALL> file for how to get it).

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.

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 C<pugs> as you
would for C<perl>:

\$ B<pugs newton>

To let Perl 6 know that I want Perl 6 and not Perl 5, I type C<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 C<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 C<say> to print the answer. This
beats writing: C<print "\$guess\n";>.

Except for using C<say> and declaring the type of the numbers to be C<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.

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 C<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;

Because C<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, I<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, C<package> identifies Perl 5 source code. The C<v6> module
(L<http://search.cpan.org/v6?v6> lets you run some Perl 6 code in Perl 5
programs.)  Immediately following is C<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 C<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 C<is export>. This puts C<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 C<Exporter> and set up C<@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.

Adding genuine, compiler-enforced parameters to sub declarations is a giant
leap forward for Perl. For many people, that particular looseness in Perl 5
keeps it out of any discussions about what language to use for a project.
I experienced this unfortunate reality firsthand in my last job. There's a
lot more to declarations in Perl 6, though.

Suppose I want to give the caller control over the accuracy of the method,
yet I want to provide a sensible default if that caller doesn't want to
think of a good one. I might write:

package Newton;
use v6;

sub newton(
Num  \$target,
Num  :\$epsilon = 0.005,  # note the colon
Bool :\$verbose = 0,
) is export {
my Num  \$guess  = \$target;

while (abs( \$guess**2 - \$target ) > \$epsilon ) {
\$guess += ( \$target - \$guess**2 ) / ( 2 * \$guess );
say \$guess if \$verbose;
}

return \$guess;
}

Here I've introduced two new optional parameters: C<\$verbose>, for whether to
print at each step (the default is to keep quiet) and C<\$epsilon>, the Greek
letter we math types often use for tolerances.

While the caller might use this exactly as before, she now has options. She
might say:

my \$answer = newton(165, verbose => 1, epsilon => .00005);

This gives extra accuracy and prints the values at each iteration (which
prints the value of the last iteration twice: once in the loop and again in
the driving script). Note that the named parameters may appear in any order.

Finally, Newton's method can find roots for more things than just squares.
To make this general requires a bit more work and some extra math (which I'll
again brush under the rug).

It is easy enough to supply the function for which you want roots. For example,
the squaring function could be:

sub f(Num \$x) { \$x**2 }

Then, in the update line of the loop, write:

\$guess += ( \$target - f(\$guess) ) / ( 2 * \$guess );

Changing C<f> would change the roots you seek.

The problem is on the far side of the division symbol. C<2 * \$guess> depends
on the function (it's the first derivative, for those who care). I could
require the caller to provide this, as in:

sub fprime(Num \$x) { 2 * \$x }

Then the update would be:

\$guess += ( \$target - f(\$guess) ) / fprime(\$guess);

There are two problems with this approach. First, you need a way for the
caller to pass those functions into the sub. That's actually pretty easy;
just add parameters of type Code to the list:

sub newton(
Num  \$target,
Code \$f,
Code \$fprime,
Num  :\$epsilon = 0.005,
Bool :\$verbose = 0,
) is export {

The second problem is that the caller may not know how to calculate C<\$fprime>.
Perhaps I should make calculus a prerequisite for using the module, but that
just might scare away a few potential users. I want to provide a default, but
the default depends on what the function is. If I knew what C<\$f> was, I could
estimate C<\$fprime> for users.

Perl 6 provides precisely this ability. Here's the final module, a bit at a
time:

package Newton;

use v6;

That's nothing new.

sub approxfprime(Code \$f, Num \$x) {
my Num \$delta = 0.1;
return (\$f(\$x + \$delta) - \$f(\$x - \$delta))/(2 * \$delta);
}

For those who care (surely at least one person does), this is a second-order
centered difference. For those who don't, its an approximation suitable for
use in the C<newton> sub. It takes a function and a number and returns an
estimate of the value needed for division.

sub newton(
Num  \$target,
Code \$f,
Code :\$fprime         = &approxfprime.assuming( f => \$f ),
Num  :\$epsilon        = 0.0005,
Bool :\$verbose        = 0,
) returns Num is export {
my Num \$guess  = \$target / 2;

while (abs(\$f(\$guess) - \$target) > \$epsilon) {
\$guess += (\$target - \$f(\$guess)) / \$fprime(\$guess);
say \$guess if \$verbose;
}

return \$guess;
}

A script using this program could be as simple as:

#!/usr/bin/pugs

use Newton;

sub f(Num \$x) { return \$x**3 }

say "{ newton(8, \&f, verbose =>; 1, epsilon =>; .00005) }";

Note that the caller must supply the function C<f>. The one in the example
is for cube roots.

If the caller provides the derivative as C<fprime>, I use it. Otherwise,
as in the example, I use C<approxfprime>. Whereas a caller-supplied C<fprime>
would take one number and return another, C<approxfprime> needs a number
and a function. The function needed is the one the caller passed to C<newton>.
How do you pass it on? CurryingE<mdash>that is, supplying one or more of the
parameters of a function once, then using the simplified version after
that.

In Perl 6, you can obtain a reference to a sub by placing the sub sigil
C<&> in front of the function's name (providing it is in scope). To curry,
add C<.assuming> to the end of that and supply values for one or more
arguments in parentheses. All of this is harder to talk about than to do:

\$fprime = &approxfprime.assuming( f => \$f ),

This code means that the caller might supply a value. If this is the case, use
it. Otherwise, use C<approxfprime> with the caller's function in place of C<f>.

Perl 6 calling conventions are extremely well designed. Not only do they
allow compile-time parameter checking, they also allow named parameters with
or without complex defaults, even including curried default functions. This
is going to be very powerful. In fact, with Pugs, it already is.

There is a slightly more detailed version of the example from this article in
the F<examples/algorithms/> directory of the Pugs distribution. It's called
F<Newton.pm>.