The Pearls of Raku, Issue 12: all and any

In this issue we’ll briefly talk about practical cases where junctions are really handy — both in syntax and in making the program simpler. Examples of using all and any junctions, checking parameters of MAIN, using in subsets.

In this issue we’ll briefly talk about practical cases where junctions are really handy — both in syntax and in making the program simpler.

Any-appetizer

Here is an interesting example of how you can use the any-junction in a single operation where you would traditionally should have a loop.

my $a = 40;
my @b = 1..5;

say 'Found the answer' if $a + any(@b) == 42;

Examine the addition $a + any(@b). We compare its result with a single number 42 as if any(@b) were a single integer.

An example of using any

A classical example of using any-junctions is something like this:

say 'There are negative ints' if 1 | -2 | 3 < 0;

An alternative syntax — use a function:

say 'There are negative ints' if any(1, -2, 3) < 0;

Another option — a method:

say 'There are negative ints' if (1, -2, 3).any < 0;

An example of using all

The following examples are similar to the examples from the previous section but employ the all-junction instead:

say 'Only positive ints' if 1 & 2 & 3 > 0;
say 'Only positive ints' if all(1, 2, 3) > 0;
say 'Only positive ints' if (1, 2, 3).all > 0;

Checking parameters of MAIN

Imagine a program that takes integer numbers from command line. You need to distinguish between the cases when the integers are either all positive or all negative.

One of the possible ways to check the input data is to use multi MAIN functions and dispatch their calls using the where clauses.

multi sub MAIN(*@a where @a.elems > 0 && .all ~~ Int && .all > 0) {
    say 'All positive integers'
}

multi sub MAIN(*@a where @a.elems > 0 && all(@a) < 0 && all(@a) ~~ Int) {
    say 'All negative integers'
}

I am using two different forms of creating the all-junction: .all and all(@a). You are free to build a WhateverCode block too.

There where clauses demand that all of the input data (i.e., the elements in @a) are integers (.all ~~ Int) and either positive (.all > 0) or negative (all(@a) < 0).

Run the program with different input data:

$ raku all-1.raku 10 20 30
All positive integers

$ raku all-1.raku -10 -20 -30
All negative integers

$ raku all-1.raku -10 -20 30
Usage:
  all-1.raku [<a> ...]
  all-1.raku [<a> ...]

Using in subsets

The previous example can be re-written in a different style that introduces new data types to the program:

subset PositiveInt of Int where * > 0;
subset PositiveIntArray of Array where .all ~~ PositiveInt && .elems > 0;

subset NegativeInt of Int where * < 0;
subset NegativeIntArray of Array where .all ~~ NegativeInt && .elems > 0;

multi sub MAIN(*@a where * ~~ PositiveIntArray) {
    say 'All positive integers'
}

multi sub MAIN(*@a where * ~~ NegativeIntArray) {
    say 'All negative integers'
}

The subsets define the rules, and you can use them directly in the where clauses in other functions.

* * *

Find the code of this issue on GitHub and browse for more Raku Pearls.

Leave a Reply

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