First Class

with Raku

This is my response to The Weekly Challenge #171.

Write a script to generate first

For example,

File: abundant-number
`20 Abundant Odd Numbers`

.
According to wikipedia,

A number n for which the sum of divisors σ(n) > 2n, or, equivalently, the sum of proper divisors (or aliquot sum) s(n) > n.For example,

`945`

is the first `Abundant Odd Number`

.
Sum of divisors:
1 + 3 + 5 + 7 + 9 + 15 + 21 + 27 + 35 + 45 + 63 + 105 + 135 + 189 + 315
= 975

#! /usr/bin/env raku
unit sub MAIN (Int :c(:$count) where $count > 0 = 20, :v(:$verbose)); # [1]
my $abundant := (1 .. Inf).grep( *.&is-abundant ); # [2]
say $abundant[^$count].join(", "); # [3]
sub divisors ($number, :$not-self, :$not-one) # [4]
{
my @divisors;
for ($not-one ?? 2 !! 1) .. $number/2 -> $candidate
{
@divisors.push: $candidate if $number %% $candidate;
}
@divisors.push: $number unless $not-self;
say ": $number -> @divisors[] = { @divisors.sum }" if $verbose;
return @divisors;
}
sub is-abundant ($number) # [5]
{
return $number % 2 && divisors($number, :not-self).sum > $number; # [6]
# return $number % 2 && divisors($number).sum > $number * 2; # [7]
}

[1] Specify another number of values to print, if the default 20 does not suit you.

[2] Start with all the integers, and use `grep`

to get only
those that we want. Note the special `.&`

calling syntax allowing us to
*pretend* that a procedure is a method.

See
docs.raku.org/language/operators#methodop_.& for more information
about the special procedure invocation syntax `.&`

.

[3] Print the required number of values from the sequence.

[4] This procedure should be familiar by now. See the second half of An Abundance of Numbers with Raku and Perl for details.

[5] Is the number abundant?

[6] Using the «Proper divisors» definition.

[7] Or you can use the «Divisors» definition.

Running it:

$ ./abundant-number
945, 1575, 2205, 2835, 3465, 4095, 4725, 5355, 5775, 5985, 6435, 6615, 6825, \
7245, 7425, 7875, 8085, 8415, 8505, 8925

Looking good.

You can use verbose mode to check the result manually, if you are so inclined. Here is a selection of the output:

$ ./abundant-number -v -c=1
: 1 -> = 0
: 3 -> 1 = 1
: 5 -> 1 = 1
: 7 -> 1 = 1
: 9 -> 1 3 = 4
: 11 -> 1 = 1
: 13 -> 1 = 1
…
: 935 -> 1 5 11 17 55 85 187 = 361
: 937 -> 1 = 1
: 939 -> 1 3 313 = 317
: 941 -> 1 = 1
: 943 -> 1 23 41 = 65
: 945 -> 1 3 5 7 9 15 21 27 35 45 63 105 135 189 315 = 975
945

Create

e.g.

`sub compose($f, $g)`

which takes in two parameters `$f`

and
`$g`

as subroutine refs and returns subroutine ref i.e.
`compose($f, $g)->($x) = $f->($g->($x))`

.
e.g.

$f = (one or more parameters function)
$g = (one or more parameters function)
$h = compose($f, $g)
$f->($g->($x,$y, ..)) == $h->($x, $y, ..) for any $x, $y, ...

Let us start with the `f`

and `g`

functions:

#! /usr/bin/env raku
my $f = sub f ($val) # [1]
{
return $val * 10;
}
my $g = sub g ($val) # [1]
{
return $val + 1;
}

[1] Two ordinary procedures, with one input value and one (deterministic) output
value. The trick (so to speak) is the fact that the `sub`

keyword returns
a reference to the procedure, and we assign that value to a variable for each one.

See
docs.raku.org/syntax/sub more information
about `sub`

.

If you want to call a function, you can either use the name (i.e. the normal way):

my $b = f(12);

Or the reference (if you have one):

```
my $b = $f(12);
```

The «compose» procedure is easy:

File: first-class-function (partial)sub compose(&f, &g) # [2]
{
return sub ($arg) # [3]
{
&f(&g($arg)); # [4]
};
}

[2] The procedure takes two arguments, of the callable type (courtesy of the `&`

(Callable) sigil). Calling it with other argument types will fail. The generic `$`

sigil works just fine, but without the Callable check.

[3] An anonymous procedure (i.e. without name), taking one input parameter (in `$arg`

).
The return value is a reference to this procedure.

[4] The procedure itself will - when executed - call the inner procedure `&g($arg)`

first, and then the outer `&f`

with the return value of the inner one.

And finally, executing the code:

File: first-class-function (the rest)my $h = compose($f, $g); # [5]
say $h(12); # [6]
say $h(13); # [7]
my $m = compose($g, $f); # [8]
say $m(12); # [9]
say $m(13);

[5] Feel free to use the `&`

(Callable) sigil here (i.e. `&h`

instead of
`$h`

), if that makes you feel better.

[6] Call the procedure(s).

[7] Ditto, with another input value.

[8] Changing the order of the procedures does matter.

[9] The same procedures, reordered, and the same input - but a different result.

Running it:

File: first-class-function (partial)$ ./first-class-function
130
140
121
131

Looking good.

And that's it.