Perl6 notes: Numbers and strings

Posted on April 29, 2023
Tags: ,

This set of notes contains a summary of what I have learned from the book Learning Perl6.

Integer

Literals

# 111 in base 2
:2<111>

# Same as 9875
98_75

Other numerical types

Similar to Scheme, Perl6 implements a numerical tower. Most importantly, in cases where applicable, Perl6 will produce rational numbers instead of floating points.

<1/3> # 0.333333
<1/3>.^mro # ((Rat) (Cool) (Any) (Mu))

<1/3> is rendered as a floating point, but there is no loss of precision in the internal representation.

Rat is not arbitrary precision. FatRat is needed if the denominator needs to be more than a \(64\)-bit integer.

FatRat.new: 1, 3
FatRat.new( 1, 3) # Same thing as above
<1/3>.FatRat # Cast from a rational literal

Smart matching

# Similar to Java's instanceof
1 ~~ Int # True

1 ~~ Str # False

# Despite its look, ~~ is not an equivalence relation
Int ~~ 1 # False

# Dispatch based on types
# given uses ~~ to match the scrutinee
sub break-parametricity (Any $v) {
    given $v {
        when Int { $v+1 }
        when Str { $v ~ "!"}
        default {False}
    }
}

break-parametricity(10) # 11
break-parametricity("hey") # hey!

Block to expression

The do keyword is similar to the begin keyword from scheme.

# Evaluates to 201
1 + do {
    my Int $x = 0;
    $x += 100;
    $x *= 2
}

Setting the topic variable with given

Just like Perl5, Perl6 supports $_ as a topic variable. In Perl6, I believe there is a saner treatment of $_ so it is lexically scoped. What the given really does is setting the topic variable. Here is given in postfix notation.

.sort.say given (1,4,3) # (1 3 4)

String literals

Perl6 comes with 「 and 」 as delimiters. Whatever appears between them are interpreted literally. Apparently these characters don’t appear often in practice so they are probably convenient for ambiguity in one-liners if your input method is set up so you can type these characters easily. I find the q/.../ form the most convenient in practice.

q/hello world/
q/"hello world"/ eq "\"hello world\"" # True
# The space is necessary so the term is not interpreted as an application
q ("hello world") eq q "\"hello world\"" # True

# q is a synonym for the following
Q :q "\"hello world\""

# Without the :q flag, Q would not allow escaping the delimiter symbol
Q "\"hello world\"" # Error

# heredoc
print Q :to/MARKER/;
  This ain't no funeral home
  It ain't the terror dome, neither
  Welcome to hell, motherfuckers
  MARKER
# Can choose MARKER to be any delimiter
# The indentations are removed
# Does not seem to work in repl

Just use q// for most of the time.

String operations

# Concatenation with ~
"hello" ~ " world"

# join for intercalate. The first argument is the separator
# note that it knows how to deal with array arguments by first flattening them
join(" ", qw/life is/, 'too', 'much')

# Repeat the string for 4 times
"rero" x 4

# Calculate the length (the number of unicode characters?)
"我爱学习".chars # 4

# Coerce to boolean
# '' is considered to be falsey
?'' # False
''.Bool # Same as above

# Str is also considered to be falsey
?Str

# To distinguish between '' and Str, use .DEFINITE
''.DEFINITE # True
Str.DEFINITE # False

# Comparisons
# Infix operators gt, eq, lt, le, ge

# Call fc on the string if non-casesensitive comparison is desired

# Trim surrounding whitespace
"\nhello\n".trim eq "hello" # True

# Trim trailng whitespace
"\nhello\n".chomp eq "\nhello" # True

# Converting to string
~1
~True

# Parse base
'0755'.parse-base(8)

# Convert back to string
0o755.base(2)

Prompting from the user

my Int $num = prompt("Input a number");
say $num+1

Interpolation

my Str $hello := "hello";
"$hello world" # hello world

qq/{$hello ~ " world"}/ # hello world
Q :qq/{$hello ~ " world"}/ # same as above

# Interpolate in a single quote
q/\qq[{$hello ~ " world"}]/ # hello world

# Uninterpolate in a double quote
qq/\q[{$hello ~ " world"}]/ # {$hello ~ " world"}

Consult the fancier quoting section from Learning Perl6 for more adverb options.

Run commands

chomp Q :x/uname/ # Linux
chomp Qx /uname/ #Same thing