Stack Overflow Asked by jjmerelo on February 24, 2021
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?
Actually, unlike I said in my previous you can use conditions in where clauses without problem, you just need to encase them in braces:
role Zipi[$condition] {
has $.floor is rw where {$_ ~~ $condition}
method foo($x) { $!floor = $x }
}
class A does Zipi[2 < * < 5] {
method bar($x) { $.floor = $x }
}
#my $a = A.new( floor => 10); # error
my $a = A.new( floor => 4); # OK
#$a.foo(10); # error
$a.foo(3); # OK
#$a.bar(0); # error
$a.bar(4); # OK
#$a.floor = 9; # error
$a.floor = 3; # OK
That should cover all of the assignment types
Correct answer by user0721090601 on February 24, 2021
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.
Answered by raiph on February 24, 2021
I have very limited MOP chops, and the following seems ugly, but it works, and might be a step in the right direction.
What I've done:
Dynamically constructed an array of 10,000 subset
s via the MOP.
Time shifted their construction to compile time via BEGIN
.
Used an appropriate element from the array to parameterize the role.
my @max-floors-checkers;
BEGIN {
@max-floors-checkers = do for ^10_000 -> floors {
Metamodel::SubsetHOW.new_type:
refinee => UInt,
refinement => { $^floors <= floors }
}
}
role BuildingCategory[ ::MaxFloorsCheck ] { has MaxFloorsCheck $.floors }
class Capped-at-three does BuildingCategory[ @max-floors-checkers[3] ] {}
my $capped3 = Capped-at-three.new( floors => 2 );
say $capped3.raku; # Capped-at-three.new(floors => 2
my $capped4 = Capped-at-three.new( floors => 4 ); # Type check failed
Answered by raiph on February 24, 2021
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.
Answered by user0721090601 on February 24, 2021
Get help from others!
Recent Questions
Recent Answers
© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP