## Using matplotlib in Perl 6 (part 1)

*2017-03-04*

This is Part of a series. You can start at the Intro here

Looking at the graphs in the Matplotlib tutorial, the first one is a straight line (boring). The second is a few red dots plotting a curve (getting better). The 3rd graph looked a more interesting: Three curved plots consisting of different patterns and colors. Here's the Python code.

import numpy as np import matplotlib.pyplot as plt # evenly sampled time at 200ms intervals t = np.arange(0., 5., 0.2) # red dashes, blue squares and green triangles plt.plot(t, t, 'r--', t, t**2, 'bs', t, t**3, 'g^') plt.show()

I ran it in python to confirm it worked as expected (it did). I then proceeded to copy and paste the code into a new Perl 6 file and changed the `import`

statements to `use`

statements.

use Matplotlib; my $plt = Matplotlib.new;

Now for the data... The `t`

values were generated by a numpy function called `arange`

. I didn't know what that did, and rather than wrap numpy as well, I figured I could probably do whatever it was doing with Perl 6. As the comment suggested, it was a simple number sequence. Perl 6 has a handy Sequence operator for just this sort of thing.

my @t = 0, 0.2 ...^ 5;

This defines a Sequence starting at 0, followed by 0.2, then increasing at the same interval until is gets up to (`^`

) 5. If I wanted to include 5 in the Sequence, I would just drop the `^`

. Using some well placed print statements, I confirmed by `@t`

values were the same as the python version.

I then pasted the rest of the Python code into my Perl script, inserted a `@`

in front of each `t`

and ran it. Things did not go as planned. Well, I got a graph, but it wasn't quite right

Some of you might have already guessed where I went wrong. Spoiler, I don't have any experience with numpy arrays (or numpy for that matter). A few more print statements let me know where I was going wrong. You see, when referring to a list (or array) in a numerical context, Perl will coerce the array to it's number of elements

my @t = (2, 3, 4); @t ** 2; # Result: 9

However numpy arrays will apply that operation to each value in the array. I could create an object in Perl 6 that behaves the same way, but for now I'll just use Perl's map function which is perfectly apt for this sort of thing. Perl 6 provides a number of ways to map values in an array: I can be very explicit, or very succinct.

@t.map(-> $x { $x ** 2 }) # Result: (4, 9, 16) @t.map(*²) # same thing

Note the lack of curlies `{}`

in the second example. This is a special syntax where `*`

takes on the value of whatever value it was passed. In fact, Perl 6 actually refers to that `*`

as `Whatever`

. This `WhateverCode`

is best suited for simple operations, which perfectly describes a binary mathematical operation such as exponentiation.

Additionally, Perl contains quite a few unicode operators; My favourites are `×`

for multiplication and `÷`

for division, instead of the historical compromise of `*`

and `/`

. In the second example above, I am using the superscript of 2 (`²`

) to raise Whatever (`*`

) to the power of 2.

I modified my arguments accordingly and ran it again. Another graph! This one also had 2 dots... But they were in a different place to last time, so that's progress, right? I looked at the gist again and noticed the arguments to `plot`

were inside square brackets. Accepting it was probably due a difference in how each language handled positional arguments, I diligently wrapped my arguments to `plot`

in square brackets.

$plt.plot([ @t, @t, 'r--', # red dashes @t, @t.map(*²), 'bs', # blue squares @t, @t.map(*³), 'g^' # green triangles ]); $plt.show();

This time when I ran it and was delighted when a graph identical to the one on the tutorial appeared before my eyes.

Wondering about those square brackets, I played around a little with the call to `plot`

. I quickly learned that Python prefers to be given what Perl calls "scalar" variables. In simple terms, a scalar is a variable that Perl will treats as a single "thing". Passing a Perl array of 3 `@things`

to a Python function would cause those 3 values to get expanded out to 3 positional arguments. Creating a scalar list `$things`

or coercing `$@things`

to be passed in a scalar context works much better.

With regard to that `map`

, it seems that by giving the `map`

directly to `plot`

, it was more "listy" than scalar. By assigning the result to a scalar first, I could then pass those values to `plot`

without having to wrap all the arguments in square brackets, like so..

my $t = [0, 0.2 ...^ 5]; my $t2 = $t.map(*²); my $t3 = $t.map(*³); $plt.plot( $t, $t, 'r--', # red dashes $t, $t2, 'bs', # blue squares $t, $t3, 'g^' # green triangles ); $plt.show();

So that about wraps up Part 1. This graph was kind of interesting, but I knew matplotlib was capable of more. I felt no great excitement from the other images in the tutorial, so headed off to the gallery to see what else I could sink my teeth into.

To be continued...