by Arne Sommer

# Self-Deceptive Methods with Raku

[123] Published 11. April 2021.

This is my response to the Perl Weekly Challenge #107.

## Challenge #107.1: Self-descriptive Numbers

I realised just before the launch this task was also part of the week 43 and contributed by Laurent Rosenfeld. It is too late to change now. Feel free to share your previous solutions if you took part in the week 43 already. I should have been more carefull, sorry.

The program from part 2 of my Olympic Numbers with Raku article looks like this:

File: selfdesc ```#! /usr/bin/env raku unit sub MAIN (UInt :\$base = 10); if \$base == any(0,1,2,3,6) || \$base > 39 { say "Error"; } elsif \$base == 5 { say "21200"; # Prevent "11100" } else { my \$number = "{ (\$base -4).base(36) }21" ~ "0" x (\$base - 3); \$number.substr-rw(*-4,1) = 1; say \$number; } ```

Follow the link above for a discussion of the code, and the result of running the program.

### Bonus

That was easy.

So let us have a go at something similarly named instead. Deceptive Numbers sound fun. (They are also called «Deceptive Non-Primes», but that is not as catchy a name.)

This is a sequence of values (integers), and we can use `gather`/`take` to collect the values:

File: deceptive-numbers ```#! /usr/bin/env raku unit sub MAIN (\$count); my \$seq := gather { my \$index = 3; # [1] loop { unless \$index.is-prime # [2] { take \$index if (10 ** (\$index -1)) % (9 * \$index) == 1; # [3] } \$index++; } } say \$seq[^\$count]; ```

[1] The article uses the term «odd prime», which means that we must skip 2 (witch is the one and only even prime).

[2] Skip primes. Note that we could have started with 1 in [1] because of this, but it does not really matter.

[3] The formulae is taken from The On-Line Encyclopedia of Integer Sequences.

See my Raku Gather, I Take article or docs.raku.org/syntax/gather take for more information about `gather`/`take`.

Running it:

```\$ ./deceptive-numbers 3 (91 259 451) \$ ./deceptive-numbers 10 (91 259 451 481 703 1729 2821 2981 3367 4141) \$ ./deceptive-numbers 20 (91 259 451 481 703 1729 2821 2981 3367 4141 4187 5461 6533 6541 6601 7471 \ 7777 8149 8401 8911) ```

We got the correct numbers.

## Challenge #107.2: List Methods

Write a script to list methods of a package/class.

Example ```package Calc; use strict; use warnings; sub new { bless {}, shift; } sub add { } sub mul { } sub div { } 1; ``` Output ```BEGIN mul div new add ```

We can get a list of methods by calling the built-in `.^methods` on an object or the class itself:

File: list-methods ```#! /usr/bin/env raku class Calc { has \$.value; # [1] has \$.next is rw; # [2] method add { … } # [3] method mul { … } method div { … } } .say for Calc.^methods; ```

[3] The three dots (`...`) or the Unicode variant `…` gives a stubbed method. The code will compile, but will throw an error if we execute one of them. (I could have used an empty body instead (`{ }`), but stubbing is useful when developing a class. If you forget to remove the dots, the program will tell you (by dying) if you try to execute it.

Note that we do not have no declare a custom «new» method, as Raku provides one for us.

Raku has Metaobject protocol (MOP) with full introspection of the Raku object system. See docs.raku.org/language/mop for more information.

Running it:

```\$ ./list-methods add # [1] mul # [1] div # [1] value # [2] next # [2] Submethod+{is-hidden-from-backtrace}.new # [3] ```

[1] The first three are as expected.

[2] Oops. These are the attributes in the class. They show up here as Raku provides access methods for us automatically. We'll look into that later.

[3] This is the builtin «new» method.

The «new» method (in [3]) does not look very nice, but we can fix that by supplying our own version of the «new» method (so that it isn't inherited). We can get rid of the access methods (in [2]) by changing the attributes to private.

File: list-methods-new ```#! /usr/bin/env raku class Calc { has \$!value; # [1] has \$!next; method new { … } # [2] method add { … } method mul { … } method div { … } } .say for Calc.^methods; ```

[1] A private attribute (with `!` instead of `.` after the sigil).

[2] A custom «new» method, replacing the built-in one.

Running it:

```\$ ./list-methods-new new add mul div BUILDALL ```

The «BUILDALL» method is probably ok (as the challenge listed a «BEGIN» method for Perl).

And that's it.