Last time we saw that a junction is something you may treat as a single value, even though it’s more than that. For example, you can add a number to three numbers at once:
my $j = 1 | 2 | 3; ($j + 10)>>.say; # 11, 12, 13, one per line
Knowing this helps us to use junctions in more complex contexts, for example, as a condition in grep or map:
say (1 .. 999).grep(* %% (3 | 5)).sum;
Here, we compute the sum of all the numbers from 1 to 999 that are divisible by 3 or 5 (999 inclusive).
A similar example with strings and first:
my @langs = <Cobol Pascal Perl Raku PHP Python>; say @langs.first(*.lc eq any(<perl raku>)); # Perl say so 'Cobol' eq any(@langs); # True
Here’s a more practical example, where a filename extension is tested without using regexes:
my $file = 'photo.bmp';
say so $file.ends-with('.jpg' | '.png' | '.gif'); # False
And this is, in fact, yet another demonstration of the TIMTOWTDI principle. You are free to choose between regexes and junctions:
my $title = 'Raku junctions explained';
say so $title.contains('Perl' | 'Raku');
say so $title.lc.contains(all <raku junction>);
say so $title.contains(none <Java Python>);
The next example selects only the Raku-related files from a list:
my @files = <main.raku notes.txt Lib.rakumod logo.png test.t>; say @files.grep(*.ends-with: any <.raku .rakumod .t>);
Now let’s use junctions in another kind of comparison, again in places where a single value is normally expected:
for <y no Yes maybe> -> $answer {
given $answer.lc {
when 'y' | 'yes' { say "$answer: agreed" }
when 'n' | 'no' { say "$answer: refused" }
default { say "$answer: ?" }
}
}
More types
Junctions work with other data types too. For example, you can use type names directly to test a variable:
for 42, 'hi', 3.14, True -> $x {
say "$x is {$x.^name}", ': ', ($x ~~ Int | Str ?? 'is' !! 'isn\'t'), ' Int or Str';
}
Note that a Boolean value is also an Int:
42 is Int: is Int or Str hi is Str: is Int or Str 3.14 is Rat: isn't Int or Str True is Bool: is Int or Str
Applying | to ranges is less obvious, but it works as expected:
for 2, 5, 8 -> $n {
say "$n: ", ($n ~~ (1..3) | (7..9) ?? 'edge' !! 'middle');
}
And a trick for the classic FizzBuzz task:
for 1 .. 15 -> $n {
say do given $n {
when * %% (3 & 5) { "$_ FizzBuzz" }
when * %% 3 { "$_ Fizz" }
when * %% 5 { "$_ Buzz" }
default { $n }
}
}
Instead of comparing the topic variable with both 3 and 5, you can compare it with 3 & 5. The program prints the correct output:
1 2 3 Fizz 4 5 Buzz 6 Fizz 7 8 9 Fizz 10 Buzz 11 12 Fizz 13 14 15 FizzBuzz
By the way, don’t forget that Raku is such a powerful language that you can create a grammar to parse Python and run a FizzBuzz.py program in a browser.
Not to mention that you can use Raku even if you don’t have it installed on your computer.