Jenis parameter di Raku, cara menggunakan nilai waktu proses sebagai parameter

Nov 28 2020

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

8 user0721090601 Nov 28 2020 at 15:51

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

5 raiph Nov 28 2020 at 04:15

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 subsets 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 
3 user0721090601 Nov 28 2020 at 01:40

Saya mencoba menggunakan whereklausa anonim , tetapi juga tidak berhasil, tetapi saya melacak masalahnya: whereklausa tersebut tampaknya diabaikan oleh BUILDmetode tersebut. Saya tidak yakin apakah itu karena memiliki akses langsung (melalui $!floor) yang melewati whereklausa, atau jika ada sesuatu yang aneh sedang terjadi (mungkin yang terakhir, saya umum dapatkan Niljika saya mencoba menggunakan nilai paramaterisasi dalam whereklausa).

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 .. ydan dapat memberikan pesan kesalahan yang lebih bermanfaat.

1 raiph Nov 29 2020 at 21:38

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 Positionalcukup analog dengan Java Collectionyang berfungsi untuk tujuan nanswer ini.

The Arrayjenis adalah parameterizable kelas . Ini menentukan struktur data yang mengikuti Positionalperan tersebut. Ini bukan daftar tertaut tetapi akan cukup untuk tujuan jawaban ini.