Raku Programming/Junctions

From Wikibooks, open books for an open world
Jump to navigation Jump to search

Junctions[edit | edit source]

Junctions 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[edit | edit source]

There 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[edit | edit source]

List 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[edit | edit source]

Another 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[edit | edit source]

Matching Junctions[edit | edit source]

Junctions, 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 | edit source]

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 | edit source]

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 | edit source]

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 | edit source]

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!