Jenis parameter di Raku, cara menggunakan nilai waktu proses sebagai parameter
Saya ingin membuat beberapa tipe parametrized untuk Raku; pada dasarnya, saya ingin membuat beberapa kelas berbeda yang perbedaan utamanya adalah kisaran nilai dari salah satu atributnya; misalnya, kelas mewakili jenis bangunan, saya ingin memiliki kelas yang berbeda untuk bangunan dengan 3 atau jumlah lantai lainnya. Jadi inilah yang terbaik yang dapat saya pikirkan:
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;
Ini jelas tidak praktis jika Anda harus mengurus banyak jumlah lantai yang berbeda (tidak di sini di Granada, di mana mereka memiliki paling banyak 10, saya pikir, tapi yah ...). Masalahnya di sini pada dasarnya Anda perlu memiliki informasi untuk subset pada waktu kompilasi, jadi kecuali Anda menggunakan makro (masih eksperimental), Anda tidak dapat menggunakan variabel apa pun. Jadi, dapatkah Anda memikirkan cara praktis untuk menentukan jenis peran kari ini untuk nilai parameter apa pun?
Jawaban
Sebenarnya, tidak seperti yang saya katakan sebelumnya, Anda dapat menggunakan kondisi di mana klausa tanpa masalah, Anda hanya perlu membungkusnya dengan kawat gigi:
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
Itu harus mencakup semua jenis tugas
Saya memiliki daging MOP yang sangat terbatas, dan yang berikut ini tampaknya jelek, tetapi berhasil, dan mungkin merupakan langkah ke arah yang benar.
Apa yang telah kulakukan:
Secara dinamis membangun array 10.000
subset
s melalui MOP.Waktu menggeser konstruksi mereka untuk mengumpulkan waktu melalui
BEGIN
.Menggunakan elemen yang sesuai dari larik untuk membuat parameter peran.
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
Saya mencoba menggunakan where
klausa anonim , tetapi juga tidak berhasil, tetapi saya melacak masalahnya: where
klausa tersebut tampaknya diabaikan oleh BUILD
metode tersebut. Saya tidak yakin apakah itu karena memiliki akses langsung (melalui $!floor
) yang melewati where
klausa, atau jika ada sesuatu yang aneh sedang terjadi (mungkin yang terakhir, saya umum dapatkan Nil
jika saya mencoba menggunakan nilai paramaterisasi dalam where
klausa).
Meskipun demikian, ini seharusnya berfungsi dengan baik, termasuk memberikan pesan kesalahan yang bermanfaat:
role Zipi[$condition] {
has $.floor; submethod BUILD(:$floor, |c) {
die "Invalid floor number."
unless $floor ~~ $condition;
$!floor = $floor;
}
}
Anda dapat melihat betapa mudahnya memodifikasi jika Anda dapat mengasumsikan lantai selalu 0 .. x
, atau x .. y
dan dapat memberikan pesan kesalahan yang lebih bermanfaat.
Sebuah jawaban yang mencakup kasus seorang pembaca tahu Java tetapi tidak Raku.
Collection<String> coll = new LinkedList<String>();
jenis parametrized untuk Raku
Contoh Java yang ditautkan adalah:
Instansiasi tipe generik dengan argumen tipe aktual disebut tipe berparameter. Contoh (dari tipe berparameter):
Collection<String> coll = new LinkedList<String>();
Analog Raku yang masuk akal adalah:
my Positional[Str] \coll = Array[Str].new;
The Positionaljenis adalah parameterizable peran . Peran menentukan antarmuka dan / atau implementasi sebagian dari suatu tipe. Saya percaya Raku Positional
cukup analog dengan Java Collection
yang berfungsi untuk tujuan nanswer ini.
The Arrayjenis adalah parameterizable kelas . Ini menentukan struktur data yang mengikuti Positional
peran tersebut. Ini bukan daftar tertaut tetapi akan cukup untuk tujuan jawaban ini.