Think Perl6-ish Variables, Expressions, and Statements

Continuing the Perl 6 adventures with Allen B. Downey's Think Python book.

Chapter 2

Maybe a brief bit about objects in Chapter 1 would be appropriate, because Perl 6 lets you query an object directly about the type associated with a value.

> 'Hello, World!'.WHAT
> 17.WHAT
> 3.2.WHAT

Strings that have numbers are still strings by default.

> '17'.WHAT
> '3.2'.WHAT

Commas make lists.

> 1,000,000
1 0 0

Variables need to be declared - my is a favorite.

> $message = 'And now for something completely different'
Variable $message is not declared
> my $message = 'And now for something completely different'
And now for something completely different

Simple string and number variables are prefixed with $. Perl 6 looks at "type" in at least two ways: the type of a value (Str, Int, Rat, and so on) and the type of the variable that holds the value. For now, just remind folks to declare variables with my and use $ sigil for the variables they're working with at this point.

> my $n = 17;
> my $pi = 3.1415926535897932

You can ask a variable what type of value it is holding right now using WHAT.

> $message.WHAT
> $n.WHAT
> $pi.WHAT

Exercise 1

Perl 6 doesn't actually care about leading zero in a value ordinarily. Caveats about literals in other languages don't apply here, except to remind folks about the difference between Int and Str.

> my $zipcode = 02492;
> $zipcode = '02492';

Rules for variable names are similar to Python and other languages, though that sigil means reserved names aren't such a big deal.

> my $76trombones = 'big parade';
Cannot declare a numeric variable
> my $more@ = 1000000
Two terms in a row
> my $class = 'Advanced Theoretical Zymurgy'
Advanced Theoretical Zymurgy

Note that Perl 6 errors are more descriptive than the infamous "SyntaxError: invalid syntax" of Python.

Oh, and Perl 6 allows - in variable names.

> my $class-name = 'Advanced Theoretical Zymurgy';
Advanced Theoretical Zymurgy

Perl 6 does not do floor division by default. It will convert Int to Rat as needed for an operation.

> my $minute = 59
> $minute / 60

Use say - remember say? - to get output when running a Perl 6 program as opposed to the interactive shell.

my $miles = 26.2
say $miles * 1.61

Run it.

$ perl6 sample-01.p6
Two terms in a row
at sample-01.p6:2
------> <BOL>⏏say $miles * 1.61
    expecting any of:
        infix or meta-infix
        infix stopper
        statement end
        statement modifier
        statement modifier loop

Yeah. Better start using semicolons now. Probably should've been using semicolons from the beginning, but I was being lazy. Speaking of lazy, I just noticed that perl6 doesn't seem to require the use v6 pragma. Still, good form is important.

use v6;
my $miles = 26.2;
say $miles * 1.61;

Run it.

$ perl6 sample-01.p6

That's better.

Assignment lines don't produce output when running outside the REPL.

use v6;
say 1;
my $x = 2;
say $x;


$ perl6 sample-02.p6

Exercise 2

Type the following statements in the Perl 6 interpreter to see what they do:

my $x = 5;
$x + 1;

Now put the same statements into a script and run it. What is the output? Modify the script by transforming each expression into a say statement and then run it again.

say 5;
my $x = 5;
say $x + 1;

Order of Operations

No huge difference here for simple operations. PEMDAS. When in doubt, use parens.

String Operations

Remember that Perl 6 is still Perl.

> '2' - 1'
> 'eggs' / 'easy'
Cannot convert string to number: base-10 number must begin with valid digits or '.' in '⏏eggs' (indicated by ⏏)

Well, almost.

Python concatenates strings with +. Perl 6 concatenates strings with ~.

my $first = 'throat';
my $second = 'warbler';
say $first ~ $second; # says 'throatwarbler'

Python does string repetition with *. Perl 6 does string repetition with x.

> 'spam' x 3


# This is a line comment, same as in loads of other languages.


Perl 6 error messages are fairly helpful.

> my $bad name = 5;
Two terms in a row

Typos are a common source of errors when caffeine passes the critical threshold. Here is one of the more common typo errors: misspelling a variable name.

> my $principal = 327.68;
> my $interest = $principle * $rate;
Variable $principle is not declared


Exercise 3

Assume that we execute the following assignment statements:

my $width = 17;
my $height = 12.0;
my $delimiter = '.';

For each of the following expressions, write the value of the expression and the type (of the value of the expression).

  1. $width / 2 = 8.5 = Rat()
  2. $width / 2.0 = 8.5 = Rat() Perl 6 just don't care about floor division
  3. $height / 3 = 4 = Rat() Looks like an Int but it's a Rat
  4. 1 + 2 * 5 = 11
  5. $delimiter x 5 = .....

Use the Perl 6 interpreter to check your answers.

Exercise 4

Practice using the Perl 6 interpreter as a calculator:

Volume of a sphere w/radius r is 4/3πr3. What is the volume of a sphere with radius 5? Python hint doesn't apply.

One solution

 use v6;
 my $radius = 5;
 my $PI = 3.1415926;
 my $area = 4/3 * $pi * $radius**3;
 say $area;

It works.

book cover prices is $24.95, bookstores get 40% discount. Shipping is $3 for first copy and 75 cents per additional copy. What's the total wholesale cost for 60 copies?

Just your basic calculator solution:

 > 24.95 * 0.6 * 60 + 0.75 * (60 - 1) + 3

I had to break the next one down carefully, as I am a bear of very small brain.

If I leave my house at 6:52 am and run 1 mile at an easy pace (8:15 per mile), then 3 miles at tempo (7:12 per mile) and 1 mile at easy pace again, what time do I get home for breakfast?

I am willing to bet good money that my solution is more verbose than it needs to be.

use v6;

my $minute = 60;
my $hour = $minute * 60;

# Turn start time to seconds after midnight
my $start-time = (6 * 60 + 52) * 60;
my $easy-pace  = 8 * 60 + 15;
my $tempo-pace = 7 * 60 + 12;
my $running-time = $easy-pace + 3 * $tempo-pace + $easy-pace;
# Find finish time as seconds after midnight
my $finish-time = $start-time + $running-time;

# Convert finish time to a clock time, first in hours:
my $finish-hour = ($finish-time / $hour).Int;
# ... then the seconds left over, expressed as minutes.
my $finish-minute = ($finish-time % $hour / 60).Int;

say "Finish time was $finish-hour:$finish-minute";

That gave me:

$ perl6 jogging.p6
Finish time was 7:30


Using a very recent Rakudo:

my $principal = 327.68;
my $interest = $principle * $rate;

Variable '$principle' is not declared.
Did you mean '$principal'?

Similar messages appear for misspelled functions and so on.

This is timotimo's first code contribution to Perl 6. He appeared on #perl6 about a year ago. He was used to Python. Interested in Perl 6. Didn't know Perl 5. Wanted to contribute this January.

timotimo implemented a levenshtein distance algorithm and integrated it in to the Rakudo compiler in short order.

One thing I find interesting about this is that someone with little idea about the internals found it relatively easy to write this code and drop it in to place.

Another is that he was able to nearly instantly port it between the compiler, Panda (the module system, for guessing module names), and NQP (a low-level compiler language that's Not Quite a subset of Perl 6).

Couple more comments.

Have you tried the amazing debugger?

constant π = 3.14 # can use unicode in variable etc. names

You can indeed much improve your date / time calculations. But rather than get in to that I'm going to recommend that you (and anyone reading along) visit the freenode IRC channel #perl6 and ask there. I'm confident they'd be delighted with your blogging and happy to comment on your code. They are very friendly to all folk, from programming novice to lisp expert.

Is your Rakudo installation just the compiler or Rakudo Star (aka Rakudo *)? The latter includes some batteries and would be ideal for what you're doing. One battery is the debugger. (Here's an article about the debugger from the 2012 Advent Calendar.) If you've installed Rakudo Star, you should be able to type perl6-debug and off you go.

The Perl 6 design comprehensively addressed Unicode in data from the start (2000) with ongoing discussion for 12 years. The same is true of Unicode in code, which works particularly nicely for an operator oriented language like Perl 6. The Unicode related entries on the the programming chrestomathy site RosettaCode illustrate the maturity gap between Perl 6 and just about every other language, including Unicode strings, Terminal control/Unicode output, String case, and String length. Visit #perl6 and they'll help you use it for code or data on whatever platform you're using.

Leave a comment

About Brian Wisti

user-pic I’m a geek in Seattle. I write code. I enjoy writing about code, regardless of whether anyone else reads it. I also knit.