Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Parametrized types in Raku, how to use run time values as parameters

Tags:

roles

raku

I'd like to create some parametrized types for Raku; basically, I'd like to create some different classes whose main difference would be the range of values of one of its attributes; for instance, classes represent types of building, I'd like to have different classes for buildings with 3 or any other number of floors. So this is the best I could think of:

subset Two-Tops of UInt where * <=2;
subset Three-Tops of UInt where * <=3;

role Zipi[ ::Capper ] {
    has Capper $.floor;
}
    
class Capped-at-three does Zipi[Three-Tops] {}


my $capped = Capped-at-three.new( floor => 2 );
say $capped.raku;

This is clearly unpractical as soon as you need to take care of many different numbers of floors (not here in Granada, where they have at most 10, I think, but well... ). The problem here is basically you need to have the information for subsets at compile time, so unless you use macros (still experimental), there's no way you can use any kind of variable. So can you think of a practical way of defining this kind of curried roles for any value of the parameter?

like image 473
jjmerelo Avatar asked Nov 27 '20 17:11

jjmerelo


2 Answers

I tried using anonymous where clauses, but similarly to no avail, but I tracked down the issue: the where clause is apparently being ignored by the BUILD method . I'm not sure if it's because it has direct access (via $!floor) which bypasses the where clause, or if something else weird is going on (probably the latter, I general got Nil if I tried to use the paramaterized value in a where clause).

Nonetheless, this should work nicely, including giving a helpful error message:

role Zipi[$condition] {
    has $.floor;

    submethod BUILD(:$floor, |c) {
        die "Invalid floor number."
            unless $floor ~~ $condition;
        $!floor = $floor;
    }
}

You can see how it'd be easy to modify if you can assume floors are always 0 .. x, or x .. y and could provide an even more helpful error message.

like image 120
user0721090601 Avatar answered Oct 20 '22 23:10

user0721090601


A nanswer covering the case a reader knows Java but not Raku.

Collection<String> coll = new LinkedList<String>();

parametrized types for Raku

The linked Java example is:

The instantiation of a generic type with actual type arguments is called a parameterized type. Example (of a parameterized type):

Collection<String> coll = new LinkedList<String>();

A reasonable Raku analog is:

my Positional[Str] \coll = Array[Str].new;

The Positional type is a parameterizable role. A role specifies an interface and/or partial implementation of a type. I believe Raku's Positional is sufficiently analogous to Java's Collection that it serves for the purposes of this nanswer.

The Array type is a parameterizable class. It specifies a data structure that adheres to the Positional role. It isn't a linked list but it will suffice for the purposes of this nanswer.

like image 33
raiph Avatar answered Oct 20 '22 21:10

raiph