Raku reblessは継承されたクラスでは機能しなくなりました


9

このスレッドで提供されたコードはもう機能しません。Perl6でオブジェクトをreblessするにはどうすればよいですか?

私は昨年このコードを書きましたが、それはうまくいきました。今はそうではありません:

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

エラーメッセージは、継承されたクラスで動作するはずなので、意味がありません。少なくともそうだった。

ドキュメントは役に立ちません。https://docs.raku.org/routine/rebless


回帰バグの可能性があります。おそらく楽道問題として報告するのが最善です。
jjmerelo

:いくつかの変更は、昨年2月ありましたgithub.com/perl6/nqp/blob/...
jjmerelo

また、@ jnthn answer docs.raku.org/type/Metamodel::Primitivesを指す脚注でドキュメントを更新しました。ありがとう、ライフ
jjmerelo

回答:


11

継承されたクラスで動作するはずです

それはそのような一般的であるはずがありませんでした。私は最初にそのAPIを設計して実装しましたが、これはミックスインの実装の詳細としてのみ意図されていました。

ごく最近まで、それは言語仕様テストスイートの一部ではありませんでした。そして、それがその一部になったとき、それは現在、より制限的なセマンティクスを持っていました。これに対する制約は、パフォーマンス上の理由から重要です。型がミックスイン操作のターゲットになる可能性がある型ではないことがわかっている場合、そのオブジェクトの属性アクセスをより単純なものにJITコンパイルできます(条件付きの追加の移動を支払った)変更前にすべての属性にアクセスし、今はミックスインターゲットタイプにのみ支払う必要があります。

MOPを使用してクラスを構築することにより、元のプログラムを変更して機能させることができます。実際、以下は完全に元のプログラムではありません。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

これは元のプログラムの最も意味的に直接的な修正ですが、より短い方法があります。型オブジェクトでbut演算子を使用しPersonてミックスイン型を生成し、それを返し、その名前を好みに合わせて調整します。

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;

とにかく、オリジナルよりも1行だけ余分です。


constant Woman = Person but role …それができることを理解していませんでした。したがって、BEGIN行に関しては、RakuはJSスタイルのプロトタイプパラダイムを実行できるようになるのをやめます。
user0721090601

OK。ご説明ありがとうございます。docs.raku.org/routine/reblessはほとんど役に立たないので、ドキュメントにその方法が見つかることを願っています...«Beginning Raku»を間もなく更新します。
Arne Sommer

@ user0721090601 RakuはS12を引用して、「クラスベースとプロトタイプベースの両方のOOプログラミング」をサポートしています。ただし、キーワードを使用してオブジェクトを作成する場合class、S12を再度引用します。「デフォルトでは、派生したオブジェクトはMu、かなり標準的なクラスベースのモデルをサポートしています... bless...呼び出し... BUILDルーチン...デフォルトのBUILDセマンティクスは、から継承されましたMu。要約すると、RakuはA)「2、3行のコードで、沼地の標準クラスベースのOOでも真剣にワープする」 B)「プロトタイプベースのOO 」をサポートすると言った方が正確だと私は主張します。
レイフ

変更点についての私の見方については、raku-musings.com / reblessed.htmlを参照してください。
Arne Sommer

5

何が起こったのreblessか、それに対して何をすべきかについての権威ある議論については、jnthnの回答を参照してください。

動作しました...今は動作しません..エラーメッセージは意味がありません...継承されたクラスで動作するはずです...少なくともそうでした...ドキュメントは役に立ちません

この(非常に長い!)回答は、Rakuプログラミング言語およびRakudoコンパイラーやdocs.raku.orgコンテンツなどの関連アーティファクトでの作業の基礎となるTDDアプローチの原理と実践のさらなる議論に興味がある人には一読に値するかもしれません。。

この回答は、Arneの元の質問の特定の部分に対する特定の回答と、この回答の以前のバージョンへの回答として彼らが書いたコメントとして構成されています。私の意図は、それが他の人にとっても有用でありながら、アルネにとってそれをより有用にすることでした。

Arne:このスレッドで与えられたコードはもう機能しません:Rakuでオブジェクトをreblessするにはどうすればよいですか?

このSOにリンクするように、そのSOに対する承認済みの回答を更新しました。

Arne:昨年このコードを書きましたが、それはうまくいきました。今ではありません

関連する変更は jnthnが書いた2019年4月のコミットで議論されまし

最近、rebless最適化を支援するために、操作のターゲットであったタイプは、ミックスインターゲットタイプとして明示的に作成する必要が始まりました。...

コメント11日rakudoのGHの問題閉じる前に「カスタムタイプにReblessをもはや動作しているようです」、と彼は書きました:

is_mixin名前付き引数が渡されるように調整する必要ClassHOW.new_typeがあります...クラス構文でそれを行う方法はないため、リバーブのターゲットタイプもMOPを使用してアセンブルする必要があります。

(上記のリンクをクリックして、推奨事項の実行方法に関するメモを参照してください。)

この問題についても、それが機能することについて少し詳しく説明します。突然機能しなくなりました...ドキュメント...以下の通話セクションをドキュメント化する必要があります。

Arne:継承されたクラスで動作するはずです。少なくともそうだった。

ロースト - R epository O F A LL PEC TのEST -楽コードが行うことになっているかを決定します。( ST ROA STは、のように読み取ることができる upposed T O S。)

、別の2019年4月のメッセージ jnthn書きました:

の以前の仕様はありませんでしたMetamodel::Primitives.reblessこのスペックテスト追加したので、今があります。これは、何が機能すると期待できるかについて、いくつかの定義があることを意味します。

Rakudoの動作が実行可能なテストスイートによって仕様化されているという事実は、Rakuが確実に動作することを保証する@Larryのアプローチの基本的な部分であり[1]、重大な影響があります[2]

この変更が広く使用されているモジュールに与える影響

これは、人気のあるInline :: Perl5モジュールで展開されたこの変更の影響のスナップショットです。

2019年4月に、ninerがその影響に関する落語GHの問題を公開しInline::Perl5ました。以下に、ninerとjnthnの間のやり取りのハイライトをいくつか抽出しました。

(元のコンテキストでは重要であったものをいくつか省略しましたが、このSOのコンテキストでは注意をそらします。この抜粋からの元の会話を完全に理解していると想定しないでください。疑問がある場合は、リンクをクリックしてください。 )

niner:私がここで行うTBHは、おそらくいつも少し怪しいものでした...それでさえも...私はそれを取り除くことができます...すでに展開されたInline :: Perl5バージョンを稼働させておくのは良いことですが。

jnthn:の以前の仕様はありませんでしたMetamodel::Primitives.rebless。[a] spectestを追加しました。これは、何が機能することが期待でき、どのInline :: Perl5が信頼できるかについて、いくつかの定義があることを意味します。

不明な名前付きパラメーターは無視されますが、:mixin以前のRakudoバージョンでは必要なかったため、以前のRakudoバージョンと今後のバージョンで動作する新しいInline :: Perl5リリースを作成することが可能になるため、少なくとも逆互換。

既存のInline :: Perl5バージョンで機能を維持する方法はないと思います...

niner:残念ながら:mixin、この場合、パスは効果がありません。なぜなら、reblessは、を介して作成されたサブクラスで行われるためMetamodel::Primitives.create_typeです。サブクラスは通常のを使用しますPerl6::ClassHOW

私はそもそもreblessハックを取り除くために大きなリファクタリングに取り組んでいます。私はこの問題を再開しているので、リリースマネージャーはrakudoのリリース候補で動作するInline :: Perl5がないことを認識しています。

jnthn: MOPを使用してそのクラスを作成しますか?もしそうならパス:is_mixinすることができPerl6::ClassHOW.new_typeます。

niner:いいえ、それはこの状況のた​​めです:class Bar is Foo { }

ドキュメントの支援

あなたが書いたこの回答の下のコメントで:

ドキュメンテーション部分をお手伝いできます

SOQの中心にある問題に対する非常に適切で有用な対応のように思えます。幸運にもこれが実現することを願っています。

それが役立つ場合

Imoテクニカルライティングは優れているので、それを改善することに関与している他の人と一緒に作業した結果がすばらしいものになることを願っています。

docs.raku.orgのコンテンツに対する基本的な制約

このような一見単​​純な質問に対するこの非常に広範な回答の残りを書いて、ジョナサンが答えた後で最初にそれを削除した後にそれを元に戻した理由の大部分は、作業の基礎となるTDDアプローチの原則と実践について議論することでしたRakuプログラミング言語と、Rakudoコンパイラやdocs.raku.orgコンテンツなどの関連アーティファクト。

Aiui、物事がRakuでどのように機能することになっているか、実際にRakudoでどのように機能するか、物事がどのようにdocs.raku.orgに文書化されることになっているのかという望ましい関係は、要約すると次のようになります。

  • すべてが永遠にボランティアプロジェクトの基本的な性質の影響を受けると推定されなければなりません。そして、その制約内で:

  • 動作ローストは すべきで文書化され、その他の動作はべきではありません。

(利用可能なボランティア時間、関心、およびコンセンサスを考慮して、ローストでカバーされていない適切にQAされた楽堂の動作を文書化するために例外が時々行われます。現在の実務では、これはリリースされた楽堂スターでの楽堂バージョンの動作を意味するようです。)

役に立たないドキュメント

ドキュメントは役に立たない

私はこれを公正なコメントだと考えました。すべてを考慮した上で、質問を書いたときのドキュメントは役に立ちませんでした。

ドキュメントは役に立たなかった[2018年]

これは非常に異なる声明です。

当時、ローストエントリのカバーはありませんでしreblessた。

上のdocs.raku.orgページrebless その動作を2018年と同じように記述しいる場合、そのときの現在の動作がサポートされていると誤って示唆されるため、役に立たないよりも悪いことになります。実際には、Rakudoの将来のバージョンでは、2018年の動作がコア開発者によって回復されるという合理的な見通しがなければ、それが壊れる可能性がありました。そして実際、これは成功しました:2018年からのサポートされていない動作は壊れ、復活しませんでした。

したがって、docs.raku.orgに何が属し、何が属さないか(上記を参照)に関するコンセンサスが与えられた場合、そのreblessページで実行できる最も役立つことは、まったく文書化reblessしないか、おそらくそのためのページを含めることですが、その動作を説明していないことを確認してください。どちらが状況でしたか:ページは存在しました。直接的には役に立たなかった。そしてそれは間違いなく何よりも優れていた。

(まだ良くなっていると想像するのは簡単です。たとえば、最新のRakudo StarのRakudoのバージョンで、関数を文書化するページに、その関数に関連するテストカバレッジの状態を文書化するパーセンテージが含まれている場合はどうでしょうか?その機能がローストでカバーされていないことに気づきました。それは、このドキュメント機能は想像しやすいですが、誰がそれを実装するのでしょうか。暦年以上の入念な作業が必要になることも想像するのは簡単です。コラボレーションを有効に実装して展開し、他のものがより重要であると考えている人々)

動作しました...突然動作しませんでした...ドキュメント...通話をドキュメント化する必要があります

動いた

それは「運」でした。

突然機能しなくなった

楽堂が改善されたからです。

ドキュメント...呼び出しをドキュメント化する必要があります

先に説明し、aiui現在のコミュニティのコンセンサスおよび/または作業の練習がある:ドキュメントはすべきで文書化し、特定のバージョン、すなわち、コールのをロースト最新RakudoスターでRakudoのバージョンのための「D行動; 他のバージョンでの動作を文書化してもよい(MAY)。

他のものを参照しないでください

Aiui、現在のコンセンサスおよび/または作業慣行は、「弱い」ドキュメントへの貢献を検討する可能性があるものです。たとえば、急いで書かれた短いコンテンツやドキュメント外のリンクなど、ボランティアがすぐに変更を反映する必要があると感じた場合に紹介することがあります。ユーザー(このSOなど)によって提起されたいくつかの懸念と、「弱い」変更を行うことは、何もしないよりはましです。もちろん、PRを行ってそれを改善することもできます(または、変更が非常に「弱い」ことで問題が悪化していると本当に感じた場合は元に戻すこともできます)。

2019.11での変更への参照は、私のカウントで7か月オフです

(これも私の計算ではそのようなものですが、コンパイラーが2019.03.1であると主張し、同じ動作のブレークポイントを備えていることを確認しました。[3]

私はJJがドキュメントを変更したと思いますが、彼はjnthnのコメントを、変更に適応する方法について誤って解釈しただけです。私は現在、何もないよりはましだと思いますが、更新するのを楽しみにしています。:)

脚注

[1]ラリーが2000年の「玉ねぎの状態」スピーチでラクにつながったプロジェクトを最初に発表した数分後、次のように述べられました。

質問:[楽]に仕様はありますか?

ラリー:私たちが特に強調したいことは、おそらく現在の回帰テストを開発するような[言語設計]仕様ではない...言語が実際に意味することの検証テストになり、実際にすべての隅を探求するそして、「これは[らく]ですが、これは[らく]ではありません」と言って、機械可読な仕様になっています。そして私にとって、それは実際には人間が読めるものの言い回しよりもはるかに重要です。

[2]もちろん、ローストは、テストがユーザーのニーズを十分にカバーしている場合にのみ、特定のユーザーに適しています。Arneの問題は、カバレッジのホールがどのように驚くべきものになるかを示しています。2018年に発生したこれらの穴の説明については、「仕様、バージョン、変更、および破損」を参照してください。朗報は、ローストはRakuで記述された多くの単体テストであり、特定の値を持つ式または構成が特定のことを行うことをテストすることです。そのため、個人や企業が新しいテストを提供してテストカバレッジを改善するのは簡単です。そして、それはすべてバージョン管理(git)の下にあるため、カスタムのダウンストリームタグ、ブランチ、フォークは、実行可能で、持続可能で、管理可能です。(実際、それが新しい言語バージョンです(ChristmasDiwaliEid(?)、など)が管理されています。)

[3]正規のnewclass is oldclass構文を使用して作成された新しいクラスをreblessにしようとする試みを、私のラップトップは機能し、repl.itでは機能ないと主張するコンパイラーを使用して機能しないことを見てきました2019.03.1。(preplumbly repl.itは、コンパイラのバージョンがに更新された直後にマスターヘッドから取得されたコンパイラソースコードのバージョンまたはそれからコンパイルされたバイナリをインストールしましたが、重大2019.03.1な変更が行われています。repl.itには彼らのオンラインラックreplを公表しました-私はそれを偶然発見しました-したがって、この状況に不都合なことは何もありませんが、$RAKU.compiler.verbose-configリンクしたばかりの動作した/壊れた出力で使用される方法の必要性を私に補強しました)


:私はどのように「rebless」作品を把握しようとしたときにドキュメントが役に立たなかったように私は、この記事を見つけた stackoverflow.com/questions/44486985/...を そして、それはその後、働いていました。そして、突然それはもはや機能しなくなり、ドキュメントはまだ役に立たなかった。コールを文書化する必要があるので、それはまだあり、他のものを参照しないでください。そして、2019.11での変更への言及は、私の計算では7か月オフです。
Arne Sommer

ドキュメンテーションパーツを手伝ってもらえれば助かります。
Arne Sommer

@ArneSommer Helping with docsから始まる私の回答の新しいセクションを参照してください。
レイフ

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.