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
Str()
> 17.WHAT
Int()
> 3.2.WHAT
Rat()
Strings that have numbers are still strings by default.
> '17'.WHAT
Str()
> '3.2'.WHAT
Str()
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;
17
> my $pi = 3.1415926535897932
3.1415926535897932
You can ask a variable what type of value it is holding right now using WHAT
.
> $message.WHAT
Str()
> $n.WHAT
Int()
> $pi.WHAT
Rat()
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;
2492
> $zipcode = '02492';
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
59
> $minute / 60
0.983333
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
===SORRY!===
Two terms in a row
at sample-01.p6:2
------> <BOL>⏏say $miles * 1.61
expecting any of:
postfix
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
42.182
That's better.
Assignment lines don't produce output when running outside the REPL.
use v6;
say 1;
my $x = 2;
say $x;
See?
$ perl6 sample-02.p6
1
2
Exercise 2
Type the following statements in the Perl 6 interpreter to see what they do:
5;
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'
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
spamspamspam
Comments
# This is a line comment, same as in loads of other languages.
Debugging
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;
327.68
> my $interest = $principle * $rate;
Variable $principle is not declared
Exercises
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).
$width / 2
=8.5
=Rat()
$width / 2.0
=8.5
=Rat()
Perl 6 just don't care about floor division$height / 3
=4
=Rat()
Looks like anInt
but it's aRat
1 + 2 * 5
=11
$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 radius5
? 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
945.45
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;
===SORRY!===
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
Thanks for the notes. I figured if I started posting some simple stupid code I'd start getting suggestions about how to make it a little less stupid.
That is very cool. Looks like I need to update my Rakudo installation.
I haven't tried the debugger, though I'd definitely be interested in learning more about it.
I know you *can* use Unicode, I just don't know how without resorting to a character map application :)
The tale continue in Chapter 3.
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.