## Author Archive

### Day 14: Going to the Rats

December 14, 2009

As I hinted at back in the in the Day 1 post, Perl 6 has rational numbers. They are created in the most straightforward fashion, by dividing an integer with another integer. But it can be a bit hard to see that there is anything unusual about the result:

```> say (3/7).WHAT
Rat()
> say 3/7
0.428571428571429
```

When you convert a Rat to a Str (for example, to “say” it), it converts to a decimal representation. This is based on the principle of least surprise: people generally expect 1/4 to equal 0.25. But the precision of the Rat is exact, rather than the approximation you’d get from a floating point number like a Num:

```> say (3/7).Num + (2/7).Num + (2/7).Num - 1;
-1.11022302462516e-16
> say 3/7 + 2/7 + 2/7 - 1
0
```

The most straightforward way to see what is going on inside the Rat is to use the `.perl` method. `.perl` is a standard Perl 6 method which returns a human-readable string which, when eval’d, recreates the original object as closely as is possible:

```> say (3/7).perl
3/7
```

You can also pick at the components of the Rat:

```> say (3/7).numerator
3
> say (3/7).denominator
7
> say (3/7).nude.perl
[3, 7]
```

All the standard numeric operators and operations work on Rats. The basic arithmetic operators will generate a result which is also a Rat if that is possible; the rest will generate Nums:

```> my \$a = 1/60000 + 1/60000; say \$a.WHAT; say \$a; say \$a.perl
Rat()
3.33333333333333e-05
1/30000
> my \$a = 1/60000 + 1/60001; say \$a.WHAT; say \$a; say \$a.perl
Num()
3.33330555601851e-05
3.33330555601851e-05
> my \$a = cos(1/60000); say \$a.WHAT; say \$a; say \$a.perl
Num()
0.999999999861111
0.999999999861111
```

(Note that the `1/60000 + 1/60000` didn’t work in the last official release of Rakudo, but is fixed in the Rakudo github repository.)

There also is a nifty method on Num which creates a Rat within a given tolerance of the Num (default is 1e-6):

```> say 3.14.Rat.perl
157/50
> say pi.Rat.perl
355/113
> say pi.Rat(1e-10).perl
312689/99532
```

One interesting development which has not made it into the main Rakudo build yet is decimal numbers in the source are now spec’d to be Rats. Luckily this is implemented in the ng branch, so it is possible to demo how it will work once it is in mainstream Rakudo:

```> say 1.75.WHAT
Rat()
> say 1.75.perl
7/4
> say 1.752.perl
219/125
```

One last thing: in Rakudo, the Rat class is entirely implemented in Perl 6. The source code is thus a pretty good example of how to implement a numeric class in Perl 6.

### Day 6: Going Into Hyperspace

December 6, 2009

pmichaud introduced Perl 6′s hyper operators yesterday. I’d like to explore these powerful meta operators further.

First, for simplicity I’m going to code a helper function, `lsay`, to easily get nice-looking output of lists. The sub is created using `our` so you can use it on the REPL.

```our sub lsay(@a) { @a.perl.say }
```

Then we can start looking at hyperoperator examples. For this post I’m going to use `>>` and `<<` instead of `»` and «, mostly because they are easier on my eyes. (I’m afraid I may need to get glasses.) `»` and « are generally considered the true form of the operator, but the longer ASCII version will work as well.

First, the most basic: adding two lists of the same length:

```> lsay (1, 2, 3, 4) <<+>> (3, 1, 3, 1)
[4, 3, 6, 5]
> lsay (1, 2, 3, 4) >>+<< (3, 1, 3, 1)
[4, 3, 6, 5]
```

If the lengths of the arrays are the same, there’s no difference between the two forms. But if the length is different:

```> lsay (1, 2, 3, 4) <<+>> (3, 1)
[4, 3, 4, 5]
> lsay (1, 2, 3, 4) >>+<< (3, 1)
Sorry, right side is too short and not dwimmy.
```

The rule is that whatever is pointed to by the pointy end of the hyperoperator can be extended if it is shorter than the other end; it is extended by repeating the last element of that list. Whatever is at the blunt end of the hyperoperator cannot be extended. All combinations are allowed, so you can specify that only the left side can be extended (`<<+<<`), only the right side (`>>+>>`), both sides can be extended (`<<+>>`), or neither side can be extended (`>>+<<`). Single scalars extend as well:

```> lsay (1, 2, 3, 4) >>+>> 2
[3, 4, 5, 6]
> lsay 3 <<+<< (1, 2, 3, 4)
[4, 5, 6, 7]
```

So that’s the basics of using hyperoperator with an infix operator. You can also use them with prefix and postfix operators:

```> lsay ~<<(1, 2, 3, 4)
["1", "2", "3", "4"]
> my @a= (1, 2, 3, 4); @a>>++; lsay @a;
[2, 3, 4, 5]
```

You can also:

```> lsay (0, pi/4, pi/2, pi, 2*pi)>>.sin
[0, 0.707106781186547, 1, 1.22464679914735e-16, -2.44929359829471e-16]
> lsay (-1, 0, 3, 42)>>.Str
["-1", "0", "3", "42"]
```

That is to say `>>.` works to call a method on every member of the list.

However much you are tempted to write `@array>>.say`, don’t do it. It may work in the current version of Rakudo, but by using the hyper operator you are promising the operation is parallelizable, and the order of the operations on the list(s) is not fixed. The hope is that future versions of Perl 6 will automatically run these operations in parallel.

Other quick notes: The hyperoperators don’t just work with the built-in set of operators. They will work with any new operator you define as well. (That works now in Rakudo, mostly.) They will work with the in-place operators, e.g. `@a >>/=>> 2` to divide an entire array by 2. (This does not work in current Rakudo.) They will work with multi-dimensional lists, with trees, and with hashes; see S03 Hyper operators. (As far as I know, these do not yet work in Rakudo either.)

I don’t know too many examples yet of source code using hyperoperators extensively, though LastOfTheCarelessMen’s Vector class is a good if straightforward start — it implements an N-dimensional vector class without a single explicit loop.

### Day 1: Getting Rakudo

December 1, 2009

There are many different partial implementations of Perl 6; at the moment, the most complete is Rakudo. There are a number of different ways to get it up and running, but if you have any interest in tracking or helping with the development, the best approach is to download directly from the source repositories and and build your own copy.

To do so, you will need Subversion (svn), git, Perl 5.8 or newer, a C compiler, and a make utility. On standard Linux-like systems (including OS X), you can build it like this:

```\$ git clone git://github.com/rakudo/rakudo.git
\$ cd rakudo
\$ perl Configure.pl --gen-parrot
\$ make
\$ make test
\$ make install```

Subversion is needed to run –gen-parrot — it actually uses svn to get the appropriate version of parrot and then compile it.  You will need to use the appropriate make command for your system.  (It’s generally `nmake` with MS Visual C++, I believe.)

For current Rakudo, `make install` doesn’t install into your path, it merely preps the system so that you can run the perl6 executable (created in the rakudo directory) from any other directory on your system. Once you have it going, you can easily play around with Perl 6 by executing `perl6` with no arguments, putting you into a REPL environment where you can type commands and see what they do. This can be incredibly handy for trying to figure out how Perl 6 works. For instance,

```\$ ./perl6
> say "Hello world!";
Hello world!
> say (10/7).WHAT
Rat()
> say [+] (1..999).grep( { \$_ % 3 == 0 || \$_ % 5 == 0 } );
233168
```

The lines starting with \$ and > are what you type; the other lines are Rakudo’s response. The first example is a simple `say` statement. The second creates a rational number and asks `WHAT` its type is (`Rat`). The third takes the list of numbers from 1 to 999, filters out the ones not divisible by 3 or 5, sums them, and then says the result. (This is Project Euler Problem #1, thanks to draegtun for reminding me of it.) We’ll try to explain how these things work in a future post.

One last thing. If you have any difficulties getting Rakudo working, the #perl6 channel on irc.freenode.net is usually very helpful.

December 1, 2009