The Pearls of Raku, Issue 8: the secrets of min (and max)

In this issue, we’ll be focusing on the built-in min function. Occasionally also on max, but the whole story is well applicable to both of them. Some of the elements can also be used with other functions.

In this issue, we’ll be focusing on the built-in min function. Occasionally, also on max, but the whole story is well applicable to both of them. Some of the elements can also be used with other functions.

How to use min

This is not a trivial question, actually 🙂 Let’s take an array with some integers, both positive and negative, and find the minimum value using different forms of the call:

my @data = 3, -2, 6, 1, 5;

say min @data;   # -2
say min(@data);  # -2
say @data.min;   # -2
say @data.min(); # -2

As you can see, both a standalone function and a method are available.

But that’s not it. You can use a reduction operator with the min function in it:

say [min] @data; # -2

According to the definition, this is equivalent to the following chain, which you can also use (but why):

say @data[0] min @data[1] min @data[2] min @data[3] min @data[4]; # -2

min of nothing

What if you apply min to an empty array? The result is logical but maybe not always intuitively straightforward.

my @a;
say @a.min; # Inf

Indeed, if you want to find a minimum element in the loop, you usually start with the first element and compare the next element with it. If you start with infinity, you do not have to make any special use of the first element to warm up the loop.

The same happens to (), Empty, Nil, or Any:

say ().min;    # Inf
say Empty.min; # Inf
say Nil.min;   # Inf
say Any.min;   # Inf

You can find more similar examples, but let me mention that with max, you get -Inf:

say @a.max;    # -Inf
say ().max;    # -Inf
say Empty.max; # -Inf
say Nil.max;   # -Inf
say Any.max;   # -Inf

min with by

The min routine accepts the named argument :by, which you can use to modify the value before the function actually makes the comparison. For example, with our initial data array, let us find the absolute minimum value:

my @data = 3, -2, 6, 1, 5;

say min(@data, :by( { abs($_) } )); # 1

I added some air around the braces and parentheses for better visibility, but you can also use the WhateverCode block to increase it further:

say min(@data, by => -*); # 6

In this example, all the elements are negated and min serves as max.

N.B.! In the case of using a method, the only optional argument &by is a positional argument, so you can’t pass it as a named parameter. Just pass the code:

say @data.min({abs($_)}); # 1
say @data.min: {abs($_)}; # 1

say @data.min: -*;        # 6

* * *

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 *