Raku — the language that speaks Unicode

Raku is by design a language that supports Unicode.

So, yes, Unicode is special for both Raku and Raku++. This all starts from the visible surface, like when you can type Greek letters and use math symbols — even easier than you do it in LaTeX (in case you know how to type in non-ASCII characters).

say τ;                       
say ∞ > 10⁹⁹;

my \φ = (1 + sqrt 5) ÷ 2;
say φ;

say 2⁵;
say 5 ∈ (2, 3, 5, 7);

sub prefix:<∑>(@a) { [+] @a }
say ∑(1, 2, 3);

You can run this program in your browser to see how it works. You can also change it a bit to try other things.

The above program was mostly about the characters that are available in the source code. But behind it, Raku knows the internal rules of the Unicode datasets, and the current Raku++ version comes with the embedded UCD 17 tables (Unicode Character Database). They are simply built in the source code, so all happens naturally.

my $family = "👨‍👩‍👧‍👦";
say $family.chars;    # 1   — one grapheme
say $family.codes;    # 7   — seven code points
say "noël".flip;      # lëon — the ë survives reversal
say "🇺🇦🇵🇱".chars;    # 2   — flags don't split

The distinction between the number of codes and characters is mostly visible as soon as you leave the ASCII space. What’s beyond it, it’s the whole Universe of different rules, collations, normalisations, names, properties, etc.

The good thing is that you do not need to think about all those Unicode internals when just using Raku and when just working with text. For example, converting to upper case has no difference in the code for “street” and “straße”.

say "straße".uc;   # STRASSE — one char becomes two
say "ffi".uc;       # FFI     — ligature expands
say "🐋".uniname; # WHALE

Diacritics are difficult because a single character (glyph) can be represented differently: say, as two distinct items for the letter and the accent, as well as as a single Unicode entry point. For Raku, it’s not difficult at all.

say "e\x[0301]" eq "é";   # True — NFG normalizes on creation
say "é".NFD.list;         # (101 769)
say "é".NFC.list;         # (233)

If you know that Unicode has literally hundreds of characters marked as digits, you may also want to use similar nice characters in the programs. Unicode fractions, Roman numbers, all that has it’s meaning and can even be used in place of Arabic digits.

say "½".unival + "⅓".unival;   # 0.833333
say "Ⅻ".unival;               # 12
say "五".unival;               # 5

Characters names and properties, even weird, are reachable with ease.

say "\c[ORCA]".uniprop("Age");  # 17.0

Regexes (and thus grammars) are no exception.

say "x𐥀y" ~~ /<:Script<Sidetic>>/;   # 「𐥀」
say "abc🐋def" ~~ /<:Emoji>/;         # 「🐋」

A couple of words about Raku++. The first phase of its development was to target the compiler against Roast, which is a huge official test suite of the Raku programming language. In total, Roast includes about 90k tests in the Unicode sections. All of them pass under Raku++. Actually, having proper support of UCD 17 helped to jump from 57% to 82% of Raku coverage, just so huge it is.

And before wrapping up, some homework for you. Below are two variants of the program that solves quadratic equations and — what is important for us today — uses a lot of non-ASCII characters. Well, and some other useful Raku features such as custom operators and junctions.

Variant 1:

sub prefix:<√>($x) {
     $x.sqrt
 }
 sub infix:<±>($p, $q) is equiv(&infix:<+>) {
     ($p + $q) | ($p - $q)
 }
 my (\a, \b, \c) = 1, -4, 3;
 if (my $D = b² − 4 × a × c) ≥ 0 {
     my $roots = (−b ± √$D) ÷ (2 × a);
     say $roots;
 }
 else {
     say "There are no real solutions";
 }

Variant 2:

sub prefix:<√>($x) {
    $x.sqrt
}
sub infix:<±>($p, $q) is equiv(&infix:<+>) {
    ($p + $q) | ($p - $q)
}
my (\a, \b, \c) = 1, -4, 3;
if (my $D = b² − 4 × a × c) ≥ 0 {
    my $roots = (−b ± √$D) ÷ (2 × a);
    say $roots;
}
else {
    say "There are no real solutions";
}

First try to understand what the programs will print, and then run them in your console.

Leave a Reply

Your email address will not be published. Required fields are marked *

Retype the CAPTCHA code from the image
Change the CAPTCHA codeSpeak the CAPTCHA code