Raku rebless tidak bekerja dengan kelas yang diwarisi lagi

9

Kode yang diberikan di utas ini tidak berfungsi lagi: Bagaimana saya bisa rebless objek di Perl 6?

Saya menulis kode ini tahun lalu, dan itu berhasil saat itu. Sekarang tidak:

class Person { ; }
class Woman is Person { ; }
my $tom = Person.new;
my $lisa = Woman.new;

say $tom.^name;  # -> Person
say $lisa.^name; # -> Woman

Metamodel::Primitives.rebless($tom, Woman);
# -> New type Woman for Person is not a mixin type

Pesan kesalahan tidak masuk akal, karena seharusnya berfungsi dengan kelas bawaan. Setidaknya begitu.

Dokumentasi tidak membantu; https://docs.raku.org/routine/rebless

Arne Sommer
sumber
Mungkin menjadi bug regresi. Mungkin lebih baik melaporkannya sebagai masalah Rakudo.
jjmerelo
Ada beberapa perubahan Februari lalu: github.com/perl6/nqp/blob/…
jjmerelo
Juga, saya telah memperbarui dokumentasi dengan catatan kaki yang menunjuk ke @jnthn answer docs.raku.org/type/Metamodel::Primitive . Terima kasih, raiph
jjmerelo

Jawaban:

11

itu seharusnya bekerja dengan kelas yang diturunkan

Seharusnya tidak seperti itu jenderal. Saya merancang API itu dan mengimplementasikannya sejak awal, dan itu hanya dimaksudkan sebagai detail implementasi mixin.

Sampai baru-baru ini, itu bukan bagian dari paket tes spesifikasi bahasa - dan ketika itu memang menjadi bagian dari itu, sudah memiliki semantik saat ini, lebih ketat,. Kendala itu penting untuk alasan kinerja: ketika kita tahu suatu tipe bukan tipe yang bisa menjadi target operasi mixin, kita dapat mengakses atribut JIT-compile pada objek itu menjadi sesuatu yang lebih sederhana (kita membayar langkah bersyarat tambahan pada setiap akses atribut sebelum perubahan, dan sekarang hanya perlu membayarnya pada tipe target mixin).

Dimungkinkan untuk memodifikasi program asli untuk bekerja dengan menggunakan MOP untuk membangun kelas. Sebenarnya, berikut ini bukan program yang asli; Saya melakukan tweak kecil demi menunjukkan bagaimana seseorang dapat memberikan metode dalam subkelas sebagai peran anonim, sehingga untuk menghindari terlalu banyak boilerplate MOP.

class Person { method m() { "person" } }
constant Woman = do {
    my \w = Metamodel::ClassHOW.new_type(:is_mixin, :name<Woman>);
    w.^add_parent(Person);
    w.^add_role(role { method m() { "woman" } });
    w.^compose()
}
my $tom = Person.new;
my $lisa = Woman.new;

say $tom.^name;  # -> Person
say $lisa.^name; # -> Woman

say $tom.m; # person
Metamodel::Primitives.rebless($tom, Woman);
say $tom.m; # woman

Walaupun itu adalah perbaikan paling semantik langsung ke program asli, ada cara yang lebih singkat: gunakan butoperator pada Personobjek tipe untuk menghasilkan tipe mixin dan kembalikan, dan kemudian sesuaikan namanya sesuai keinginan Anda:

class Person { method m() { "person" } }
constant Woman = Person but role { method m() { "woman" } }
BEGIN Woman.^set_name('Woman');

my $tom = Person.new;
my $lisa = Woman.new;

say $tom.^name;  # -> Person
say $lisa.^name; # -> Woman

say $tom.m;
Metamodel::Primitives.rebless($tom, Woman);
say $tom.m;

Yang hanya satu baris ekstra dari yang asli pula.

Jonathan Worthington
sumber
constant Woman = Person but role …Tidak menyadari bahwa itu bisa dilakukan. Dan dengan demikian tetapi untuk BEGINgaris, Raku hampir berhasil melakukan paradigma prototipe gaya JS juga!
user0721090601
Baik. Terima kasih atas penjelasannya. Saya berharap itu akan menemukan jalannya ke dalam dokumentasi, karena docs.raku.org/routine/rebless sangat tidak berguna ... Saya akan segera memperbarui «Beginning Raku».
Arne Sommer
@ user0721090601 Raku mendukung, mengutip S12: "baik pemrograman OO berbasis kelas dan prototipe" . Namun, jika Anda membuat objek menggunakan classkata kunci , maka, mengutip S12 lagi: "secara default, objek yang berasal dari Mumendukung model berbasis kelas yang cukup standar ... bless... panggilan ... BUILD rutin ... standar semantik BUILD adalah diwarisi dari Mu". Singkatnya, saya berpendapat bahwa lebih akurat untuk mengatakan bahwa Raku mendukung A) "serius membengkokkan bahkan standar standar berbasis rawa babi hanya dengan beberapa baris kode" dan B) "OO berbasis prototipe."
raiph
Lihat raku-musings.com/reblessed.html untuk pandangan saya tentang memecah perubahan.
Arne Sommer
5

Lihat jawaban jnthn untuk diskusi resmi tentang apa yang terjadi reblessdan apa yang harus dilakukan.

itu berfungsi ... Sekarang tidak .. Pesan kesalahan tidak masuk akal ... itu seharusnya bekerja dengan kelas yang diwarisi ... Setidaknya itu ... Dokumentasi tidak membantu

Jawaban (sangat panjang!) Ini mungkin layak dibaca bagi mereka yang tertarik untuk berdiskusi lebih lanjut tentang prinsip-prinsip dan praktik pendekatan TDD yang mendasari kerja pada bahasa pemrograman Raku dan artefak terkait seperti konten Rakudo dan konten docs.raku.org .

Jawaban ini disusun sebagai respons spesifik terhadap bagian tertentu dari pertanyaan awal Arne dan komentar yang mereka tulis sebagai tanggapan terhadap versi sebelumnya dari jawaban ini. Maksud saya adalah untuk membuatnya lebih bermanfaat bagi Arne sementara, semoga, tetap bermanfaat bagi orang lain.

Arne: Kode yang diberikan di utas ini tidak berfungsi lagi: Bagaimana saya bisa rebless objek di Raku?

Saya telah memperbarui jawaban yang diterima untuk SO itu untuk menautkan ke SO ini.

Arne: Saya menulis kode ini tahun lalu, dan berhasil kemudian. Sekarang tidak

Perubahan yang relevan dibahas dalam komitmen April 2019 di mana jnthn menulis:

Baru-baru ini, tipe yang menjadi target reblessoperasi mulai perlu dibuat secara eksplisit sebagai tipe target mixin, untuk membantu optimasi. ...

Dalam komentar 11 hari yang lalu menutup masalah rakudo GH "Tidak dapat diubah menjadi tipe kustom tidak lagi berfungsi" , ia menulis:

Anda harus mengatur agar is_mixinargumen yang dinamai diteruskan ke ClassHOW.new_type... Tidak ada cara untuk melakukan itu dengan sintaksis kelas, sehingga tipe target dari rebless harus dikumpulkan menggunakan MOP juga.

(Klik tautan di atas untuk catatan tentang bagaimana melakukan apa yang disarankan.)

Masalah ini juga dibahas sedikit lebih jauh dalam kerjanya ... tiba-tiba tidak ... dokumentasi ... harus mendokumentasikan bagian panggilan di bawah ini.

Arne: itu seharusnya bekerja dengan kelas bawaan. Setidaknya begitu.

panggang - yang r epository o f suatu ll s PEC t EST - menentukan apa kode Raku yang seharusnya dilakukan. (The st dari roa st dapat dibaca sebagai s upposed t o s.)

Dalam pesan April 2019 yang lain, jnthn menulis:

Tidak ada spesifikasi sebelumnya untuk Metamodel::Primitives.rebless. Saya sudah menambahkan spectest ini sehingga sekarang ada. Ini berarti sekarang ada beberapa definisi tentang apa yang bisa diharapkan berfungsi.

Fakta bahwa perilaku Rakudo ditentukan oleh suite uji yang dapat dieksekusi adalah bagian mendasar dari pendekatan @ Larry untuk memastikan Raku berperilaku andal [1] dan memiliki implikasi mendalam [2] .

Dampak dari perubahan ini pada modul yang banyak digunakan

Berikut adalah snapshot dari dampak perubahan ini yang sedang berlangsung untuk modul Inline :: Perl5 yang populer.

Pada bulan April 2019, niner membuka masalah rakudo GH tentang dampaknyaInline::Perl5 dan saya telah mengekstraksi beberapa sorotan dari pertukaran antara niner dan jnthn di bawah ini.

(Saya telah menghilangkan beberapa hal yang penting dalam konteks asli, tetapi mengganggu dalam konteks SO ini. Harap jangan menganggap Anda memiliki pemahaman yang lengkap tentang percakapan asli dari ekstrak ini. Jika ragu, klik tautannya. )

niner: TBH apa yang saya lakukan di sini mungkin selalu agak mencurigakan ... Bahkan bisa jadi ... saya bisa menyingkirkannya ... Akan lebih baik meskipun tetap digunakan Inline :: Versi Perl5 aktif dan berjalan .

jnthn: Tidak ada spesifikasi sebelumnya untuk Metamodel::Primitives.rebless. Saya telah menambahkan [a] tontonan sehingga sekarang ada. Ini berarti sekarang ada beberapa definisi tentang apa yang dapat diharapkan untuk bekerja, dan yang Inline :: Perl5 dapat andalkan.

Karena parameter bernama yang tidak diketahui diabaikan, tetapi :mixintidak diperlukan pada versi Rakudo sebelumnya, maka dimungkinkan untuk membuat rilis Inline :: Perl5 baru yang dapat bekerja pada versi Rakudo sebelumnya serta yang akan datang, sehingga setidaknya bisa ada back-compat.

Saya tidak berpikir ada cara untuk menjaga hal-hal yang berfungsi untuk versi Inline :: Perl5 yang ada ...

niner: Sayangnya lewat :mixintidak membantu dalam kasus ini karena rebless dilakukan pada subkelas dari yang dibuat via Metamodel::Primitives.create_type. Subclass menggunakan normal Perl6::ClassHOW.

Saya sedang mengerjakan refactor utama untuk menyingkirkan retless reback di tempat pertama. Saya membuka kembali masalah ini sehingga manajer rilis menyadari bahwa tidak ada Inline yang berfungsi :: Perl5 pada kandidat rilis rakudo.

jnthn: Apakah Anda membuat kelas itu menggunakan MOP? Anda dapat melewati :is_mixinke Perl6::ClassHOW.new_typejika demikian.

niner: Tidak, ini untuk situasi ini:class Bar is Foo { }

Membantu dengan dokumen

Dalam komentar di bawah, jawaban ini Anda tulis:

Saya dapat membantu dengan bagian dokumentasi

Bagi saya itu kedengarannya seperti respons yang sangat tepat dan berguna untuk masalah yang menjadi inti dari SOQ Anda. Saya harap kita cukup beruntung sehingga ini terjadi.

jika itu membantu

Imo tulisan teknis Anda sangat bagus sehingga saya berharap hasil akhir dari Anda bekerja dengan orang lain yang terlibat dalam peningkatan itu akan menjadi hal yang luar biasa.

Kendala mendasar pada konten docs.raku.org

Sebagian besar alasan saya menulis sisa dari jawaban yang sangat luas ini untuk pertanyaan yang tampaknya sederhana, dan mengembalikannya setelah awalnya menghapusnya begitu Jonathan menjawabnya, adalah untuk membahas prinsip-prinsip dan praktik pendekatan TDD yang mendasari kerja pada bahasa pemrograman Raku dan artefak terkait seperti kompilator Rakudo dan konten docs.raku.org .

Aiui, hubungan yang diinginkan antara bagaimana hal-hal seharusnya bekerja di Raku, dan bagaimana mereka sebenarnya bekerja di Rakudo, dan bagaimana hal-hal yang seharusnya didokumentasikan di docs.raku.org bermuara pada:

  • Semuanya HARUS dianggap selamanya tunduk pada sifat dasar dari proyek sukarela; dan, dalam batasan itu:

  • Perilaku dalam panggang HARUS didokumentasikan dan perilaku lainnya TIDAK HARUS.

(Mengingat waktu sukarela, minat, dan konsensus yang tersedia, pengecualian kadang-kadang dibuat untuk mendokumentasikan perilaku Rakudo QA'd yang benar yang tidak tercakup oleh daging panggang. Dalam praktik saat ini, ini tampaknya berarti perilaku versi Rakudo dalam Bintang Rakudo yang dirilis.)

Dokumentasi tidak berguna

Dokumentasi tidak membantu

Saya menganggap ini komentar yang adil. Semua hal dipertimbangkan, dokumentasi seperti ketika Anda menulis pertanyaan Anda tidak membantu.

dokumentasi tidak berguna [pada tahun 2018]

Ini pernyataan yang sangat berbeda.

Tidak ada entri panggang menutupi reblesspada saat itu.

Jika halaman docs.raku.org pada rebless harus dijelaskan perilakunya seperti di 2018, maka yang akan menjadi lebih buruk daripada tidak berguna karena tidak benar akan menyarankan bahwa perilaku maka saat ini didukung. Pada kenyataannya ada ruang untuk memecahkan dalam versi Rakudo di masa depan tanpa prospek yang masuk akal perilaku 2018 akan dipulihkan oleh para pengembang inti. Dan memang ini terjadi: perilakunya yang tidak didukung sejak 2018 benar-benar hancur, dan tidak dipulihkan.

Jadi, mengingat konsensus tentang apa yang termasuk dalam docs.raku.org dan apa yang tidak (lihat di atas), hal yang paling membantu reblesshalamannya dapat lakukan adalah tidak mendokumentasikan reblesssama sekali atau, mungkin lebih baik, termasuk halaman untuk itu tetapi pastikan itu tidak menggambarkan perilakunya. Itulah situasinya: halaman itu memang ada; tidak langsung membantu; dan itu bisa dibilang lebih baik daripada tidak sama sekali.

(Sangat mudah untuk membayangkan hal-hal yang lebih baik. Misalnya, bagaimana jika fungsi mendokumentasikan halaman termasuk persentase mendokumentasikan keadaan cakupan pengujian yang terkait dengan fungsi itu dalam versi Rakudo di Rakudo Star terbaru? 0% dapat langsung memberi petunjuk kepada pembaca ke kesadaran bahwa fungsi itu tidak tercakup oleh panggang. Yang mengatakan, sementara fitur doc ini mudah dibayangkan , siapa yang akan mengimplementasikannya? Sama mudahnya untuk membayangkan bahwa itu bisa memakan waktu satu tahun kalender atau lebih dari pekerjaan yang rajin dan kolaborasi untuk mengimplementasikan dan menyebarkan, dan orang-orang berpikir hal-hal lain lebih penting.)

itu berhasil ... tiba-tiba tidak ... dokumentasi ... harus mendokumentasikan panggilan

itu berhasil

Itu "keberuntungan" itu berhasil.

tiba-tiba itu tidak berfungsi lagi

Karena Rakudo ditingkatkan.

dokumentasi ... harus mendokumentasikan panggilan

Sebagaimana dijelaskan sebelumnya, yang juga merupakan konsensus komunitas saat ini dan / atau praktik kerja adalah: dokumentasi HARUS mendokumentasikan versi tertentu dari panggilan tersebut, yaitu perilaku daging panggang untuk versi Rakudo dalam Rakudo Star terbaru; dan MUNGKIN perilaku dokumen di versi lain.

dan tidak merujuk ke hal lain

Aiui, konsensus saat ini dan / atau praktik kerja adalah bahwa apa yang beberapa orang mungkin anggap sebagai kontribusi dokumen "lemah", misalnya beberapa konten singkat, dan / atau tautan di luar dokumen, MUNGKIN diperkenalkan jika sukarelawan merasakan perubahan segera dijamin untuk mencerminkan beberapa kekhawatiran yang dikemukakan oleh pengguna (mis. SO ini) dan bahwa membuat perubahan "lemah" akan lebih baik daripada tidak melakukan apa-apa sama sekali. Anda tentu saja dapat melakukan PR untuk memperbaikinya (atau mengembalikannya jika Anda benar-benar merasa bahwa perubahan itu "sangat lemah" sehingga memperburuk keadaan).

referensi untuk perubahan pada 2019.11 adalah 7 bulan dengan hitungan saya

(Itu adalah hal seperti itu menurut hitungan saya juga, meskipun saya telah melihat kompiler mengklaim 2019.03.1 dengan istirahat yang sama dalam perilaku. [3] )

Saya pikir JJ membuat perubahan dokumen dan dia hanya salah mengartikan komentar jnthn tentang bagaimana beradaptasi dengan perubahan. Saat ini saya pikir ini lebih baik daripada tidak sama sekali tetapi berharap Anda memperbaruinya. :)

Catatan kaki

[1] Berikut ini dikatakan beberapa menit setelah Larry pertama kali mengumumkan proyek yang mengarah ke Raku dalam pidatonya "State of the Onion" tahun 2000 :

Pertanyaan: Apakah [Raku] punya spesifikasi?

Larry: apa yang secara khusus ingin kami tekankan ... mungkin bukan [desain bahasa] spesifik seperti mengembangkan tes regresi kami saat ini ... menjadi tes validasi tentang arti sebenarnya dari bahasa tersebut dan benar-benar keluar dan menjelajahi semua sudut dan cranny dan berkata, "Ini [Raku], ini bukan [Raku]," dan kemudian kita benar-benar memiliki spek yang dapat dibaca mesin. Dan bagi saya itu sebenarnya jauh lebih penting daripada apa yang dikatakan dalam hal yang dapat dibaca manusia.

[2] Tentu saja, panggang hanya berfungsi dengan baik untuk pengguna tertentu jika pengujiannya cukup untuk memenuhi kebutuhan pengguna. Masalah Arne menunjukkan bagaimana lubang dalam liputan bisa mengejutkan. Untuk diskusi tentang lubang-lubang ini saat mereka berdiri pada 2018, lihat Spesifikasi, Versi, Perubahan, dan ... Kerusakan . Berita baiknya adalah panggang hanya banyak unit test yang ditulis dalam Raku untuk menguji bahwa ekspresi atau konstruksi dengan nilai tertentu melakukan hal tertentu. Jadi mudah bagi individu atau perusahaan untuk berkontribusi tes baru untuk meningkatkan cakupan tes. Dan semuanya berada di bawah kontrol versi (git), jadi tag hilir khusus, cabang, dan garpu layak, berkelanjutan, dan dikelola. (Memang, itu bagaimana baru versi bahasa ( Christmas, Diwali, Eid(?), Dll) dikelola.)

[3] Saya telah melihat upaya untuk me-rebest sebuah kelas baru yang dibuat menggunakan newclass is oldclasssintaks biasa, keduanya berfungsi (pada laptop saya) dan tidak berfungsi (pada repl.it) menggunakan kompiler yang mengklaim dirinya sebagai 2019.03.1. (Presumbly repl.it menginstal versi dari kode sumber kompilator, atau biner disusun dari itu, diambil dari kepala sekolah lama setelah versi compiler telah diupdate untuk 2019.03.1, dengan perubahan melanggar di tempat. Saya perhatikan bahwa repl.it haven' t mempublikasikan raku online mereka - saya menemukannya secara tidak sengaja - jadi tidak ada yang tidak diinginkan tentang situasi ini tetapi itu menguatkan bagi saya perlunya $RAKU.compiler.verbose-configmetode yang digunakan dalam output yang bekerja / rusak yang baru saja saya tautkan.)

raiph
sumber
Saya menemukan artikel ini ketika saya mencoba mencari tahu bagaimana "rebless" bekerja, karena dokumentasinya tidak berguna: stackoverflow.com/questions/44486985/… Dan itu berhasil, lalu. Dan tiba-tiba itu tidak berfungsi lagi, dan dokumentasinya masih tidak berguna. Masih, karena harus mendokumentasikan panggilan, dan tidak merujuk ke hal lain. Dan referensi untuk perubahan pada 2019.11 adalah 7 bulan dengan hitungan saya.
Arne Sommer
Saya dapat membantu dengan bagian dokumentasi, jika itu membantu.
Arne Sommer
@ArneSommer Silakan lihat bagian baru dalam jawaban saya mulai dengan Membantu dengan dokumen .
raiph