Raku Programming/Junctions
Junctions
editJunctions were originally implemented as part of a fancy Perl module to simplify some common operations. Let's say we have a complex condition where we need to test variable $x
against one of several discrete values:
if ($x == 2 || $x == 4 || $x == 5 || $x == "hello"
|| $x == 42 || $x == 3.14)
This is a huge mess. What we want to do is basically create a list of values and ask "if $x
is one of these values". Junctions allow this behavior, but also do so much more. Here's the same statement written as a junction:
if ($x == (2|4|5|"hello"|42|3.14))
Types of Junctions
editThere are 4 basic types of junctions: any (logical OR of the components), all (logical AND of all components), one (logical XOR of all components), and none (logical NOR of the components).
List Operators
editList operators construct a junction as a list:
my $options = any(1, 2, 3, 4); # Any of these is good
my $requirements = all(5, 6, 7, 8); # All or nothing
my $forbidden = none(9, 10, 11); # None of these
my $onlyone = one(12, 13, 4); # One and only one
Infix Operators
editAnother way to specify a junction is to use infix operators like we have already seen:
my $options = 1 | 2 | 3 | 4; # Any of these is good
my $requirements = 5 & 6 & 7 & 8; # All or nothing
my $onlyone = 12 ^ 13 ^ 4; # One and only one
Notice that there isn't an infix operator to create none()
junctions.
Operations on Junctions
editMatching Junctions
editJunctions, like any other data type in Raku, can be matched against using the smart match operator ~~
. The operator will automatically perform the correct matching algorithm depending on which type of junction is being matched.
my $junction = any(1, 2, 3, 4);
if $x ~~ $junction {
# execute block if $x is 1, 2, 3, or 4
}
all()
Junctions
edit
if 1 ~~ all(1, "1", 1.0) # Success, all of them are equivalent
if 2 ~~ all(2.0, "2", "foo") # Failure, the last one doesn't match
An all()
junction will only match if all the elements in it match the object $x
. If any of the elements do not match, the entire match fails.
one()
Junctions
edit
A one()
junction will only match if exactly one of its elements match. Any more or any less, and the entire match fails.
if 1 ~~ one(1.0, 5.7, "garbanzo!") # Success, only one match
if 1 ~~ one(1.0, 5.7, Int) # Failure, two elements match
any()
Junctions
edit
An any()
junction matches so long as at least one element matches. It could be one or any other number but zero. The only way for an any
junction to fail is if none of the elements match.
if "foo" ~~ any(String, 5, 2.18) # Success, "foo" is a String
if "foo" ~~ any(2, Number, "bar") # Failure, none of these match
none()
Junctions
edit
none()
junctions only succeed in a match if none of the elements in the junction match. In this way, it's equivalent to the inverse of the any()
junction. If any()
succeeds, none()
fails. If any()
fails, none()
succeeds.
if $x ~~ none(1, "foo", 2.18)
if $x !~ any(1, "foo", 2.18) # Same thing!