Junctions
2026-03-29
Junctions are one of Raku's most unique features. They represent a value that is simultaneously multiple values at once. When you test a junction, the test is applied to all its values automatically. Think of them as quantum superpositions for your code.
The Four Junction Types
Raku provides four junction constructors:
my $color = any('red', 'green', 'blue');
say 'red' eq $color;
say 'yellow' eq $color;
my $positive = all(1, 5, 10, 20);
say $positive > 0;
say $positive > 5;
my $special = one(1, 2, 3);
say $special == 2;
say $special > 0;
my $forbidden = none('admin', 'root', 'superuser');
say 'guest' eq $forbidden;
say 'admin' eq $forbidden;
Shorthand Operators
Raku provides shorthand operators for creating junctions:
say 5 == 3|5|7;
say 6 > 1&2&3;
say 5 == 4^5^6;
Junctions in Conditionals
Junctions shine in if statements:
my $input = "quit";
if $input eq "quit"|"exit"|"q" {
say "Goodbye!";
}
my $age = 25;
if $age > all(18, 21) {
say "Old enough everywhere";
}
This is much cleaner than writing if $input eq "quit" || $input eq "exit" || $input eq "q".
Auto-threading
When a junction is passed to a function, Raku automatically calls the function for each value in the junction. This is called auto-threading:
sub is-even($n) { $n %% 2 }
say is-even(2|4|6);
say is-even(1|2|3);
Junctions with Smart Match
Junctions work beautifully with ~~ (smart match):
my @valid-extensions = <.jpg .png .gif .webp>;
my $file = "photo.jpg";
if $file.ends-with(any(@valid-extensions)) {
say "Valid image file!";
}
Filtering with Junctions
Use junctions to filter lists concisely:
my @numbers = 1..20;
my @divisible-by-3-or-5 = @numbers.grep(* %% 3|5);
say @divisible-by-3-or-5;
my @not-forbidden = <alice bob admin carol root>.grep(* ne all('admin', 'root'));
say @not-forbidden;
Range Validation
Junctions make range checks elegant:
sub validate-port(Int $port) {
if $port == none(0..1023) && $port == any(1024..65535) {
say "Valid unprivileged port: $port";
} else {
say "Invalid or privileged port: $port";
}
}
validate-port(8080);
validate-port(80);
Junctions Are Not Lists
An important distinction: junctions are not iterable containers. You cannot loop over a junction or access its elements directly:
my $j = any(1, 2, 3);
say $j.eigenstates;
Junctions are meant for boolean tests, not for data storage.
Practical Example: Input Validation
sub validate-user(%data) {
my @errors;
@errors.push("Name required") unless %data<name>.defined && %data<name>.chars > 0;
if %data<age>.defined {
@errors.push("Invalid age") unless 13 <= %data<age> <= 120;
}
if %data<role>.defined {
@errors.push("Invalid role") unless %data<role> eq any('user', 'editor', 'admin');
}
@errors.push("Invalid email") unless %data<email>.defined && %data<email>.contains('@');
return @errors;
}
my %user = name => "Alice", age => 25, role => "editor", email => "alice@example.com";
my @errs = validate-user(%user);
say @errs.elems == 0 ?? "Valid!" !! @errs;
Junctions with Custom Types
Junctions work with any type that supports the operations you use:
class Temperature {
has $.degrees;
has $.scale = 'C';
method Numeric() { $!degrees }
}
my $readings = any(
Temperature.new(degrees => 36.5),
Temperature.new(degrees => 37.2),
Temperature.new(degrees => 38.9),
);
if $readings > 38 {
say "Someone has a fever!";
}
Combining Junctions
Junctions can be combined:
my $weekday = any('Mon', 'Tue', 'Wed', 'Thu', 'Fri');
my $weekend = any('Sat', 'Sun');
my $day = 'Wed';
say "Workday!" if $day eq $weekday;
say "Weekend!" if $day eq $weekend;
my $valid-day = any($weekday, $weekend);
say "Valid day" if $day eq $valid-day;
Performance Considerations
Junctions are optimized in Rakudo, but keep in mind:
- Small junctions (fewer than 20 elements) are very efficient
- For large datasets,
.grep with a closure may be faster than constructing a huge junction
- Junctions are evaluated eagerly, so
any(1..1000000) creates all values upfront
if $status eq any('ok', 'success', 'done') { ... }
my %valid = set('a'..'z');
if %valid{$char} { ... }
Junctions provide a concise, expressive way to write multi-value comparisons and validations. They are one of those features that, once learned, you will reach for constantly.