Raku Rebbless nie działa już z klasami odziedziczonymi

9

Kod podany w tym wątku już nie działa: Jak mogę zbuntować obiekt w Perlu 6?

Napisałem ten fragment kodu w zeszłym roku i wtedy zadziałało. Teraz nie:

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

Komunikat o błędzie nie ma sensu, ponieważ powinien działać z klasami dziedziczonymi. Tak przynajmniej było.

Dokumentacja nie jest pomocna; https://docs.raku.org/routine/rebless

Arne Sommer
źródło
Może to być błąd regresji. Prawdopodobnie najlepiej zgłosić to jako problem Rakudo.
jjmerelo
W lutym było kilka zmian: github.com/perl6/nqp/blob/…
jjmerelo
Zaktualizowałem również dokumentację przypisem wskazującym na @jnthn answer docs.raku.org/type/Metamodel::Primitives . Dzięki, raiph
jjmerelo

Odpowiedzi:

11

ma działać z klasami dziedziczonymi

To nigdy nie miało być tak ogólne. Zaprojektowałem ten interfejs API i zaimplementowałem go w pierwszej kolejności, a jego przeznaczeniem był tylko szczegół implementacji mixinów.

Do niedawna nie był częścią zestawu testów specyfikacji języka - a kiedy stał się jego częścią, miał już swoją obecną, bardziej restrykcyjną semantykę. Ograniczenia na nim są ważne ze względu na wydajność: kiedy wiemy, że typ nie jest celem, który może być celem operacji mixin, możemy uzyskać dostęp do atrybutu kompilacji JIT dla tego obiektu w coś znacznie prostszego (zapłaciliśmy dodatkowy ruch warunkowy dostęp do wszystkich atrybutów przed zmianą, a teraz trzeba płacić tylko za typy docelowe mixin).

Możliwe jest zmodyfikowanie oryginalnego programu do pracy za pomocą MOP do zbudowania klasy. W rzeczywistości poniższe programy nie są oryginalnym programem; Zrobiłem drobną poprawkę, aby pokazać, jak można zapewnić metody w podklasie jako anonimową rolę, aby uniknąć zbyt dużej liczby płyt 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

Chociaż jest to najbardziej semantycznie bezpośrednia poprawka do oryginalnego programu, istnieje krótszy sposób: użyj butoperatora na Personobiekcie typu, aby utworzyć typ miksu i zwróć go, a następnie dostosuj jego nazwę do własnych upodobań:

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;

Co i tak jest tylko jedną linią dodatkową niż oryginał.

Jonathan Worthington
źródło
constant Woman = Person but role …Nie zdawałem sobie sprawy, że można to zrobić. I tak, ale jeśli chodzi o BEGINlinię, Raku właśnie zaczyna robić prototypowy paradygmat w stylu JS!
user0721090601
Ok. Dziękuję za wyjaśnienie. Mam nadzieję, że trafi do dokumentacji, ponieważ docs.raku.org/routine/rebless jest dość bezużyteczny ... Niedługo zaktualizuję „Beginning Raku”.
Arne Sommer
@ user0721090601 Obsługuje Raku, cytując S12: „zarówno programowanie OO w oparciu o klasy, jak i prototyp” . Jednakże, jeśli budować obiekty za pomocą classsłowa kluczowego , a następnie, powołując S12 znowu: „Domyślnie obiekty pochodzące ze Muwsparcia dość standardowy model klasy oparte ... bless... rozmowy ... rutyny budowy ... domyślnym BUILD semantyka odziedziczony z Mu”. Podsumowując, twierdzę, że dokładniej jest powiedzieć, że Raku obsługuje A) „poważnie wypacza nawet OO oparte na klasach OO za pomocą zaledwie kilku linii kodu” i B) „OO oparte na prototypie”.
raiph
Zobacz mój adres na łamanie zmian na stronie raku-musings.com/reblessed.html .
Arne Sommer
5

Zobacz odpowiedź jnthna, aby uzyskać autorytatywną dyskusję na temat tego, co dokładnie się stało reblessi co z tym zrobić.

działało ... Teraz nie działa ... Komunikat o błędzie nie ma sensu ... powinien działać z klasami odziedziczonymi ... Przynajmniej tak było ... Dokumentacja nie jest pomocna

Ta (bardzo długa!) Odpowiedź może być warta przeczytania dla osób zainteresowanych dalszą dyskusją na temat zasad i praktyki podejścia TDD, które leży u podstaw pracy nad językiem programowania Raku i powiązanymi artefaktami, takimi jak kompilator Rakudo i zawartość docs.raku.org .

Ta odpowiedź składa się z konkretnych odpowiedzi na poszczególne części pierwotnego pytania Arne i komentarzy, które napisali w odpowiedzi na wcześniejszą wersję tej odpowiedzi. Moim zamiarem było uczynienie go bardziej użytecznym dla Arne, a jednocześnie, mam nadzieję, nadal przydatnym dla innych.

Arne: Kod podany w tym wątku już nie działa: Jak mogę zmienić obiekt w Raku?

Zaktualizowałem zaakceptowaną odpowiedź na to pisemne zgłoszenie zastrzeżeń, aby utworzyć link do tego pisemnego zgłoszenia zastrzeżeń.

Arne: Napisałem ten fragment kodu w zeszłym roku i wtedy zadziałało. Teraz tak nie jest

Odpowiednią zmianę omówiono w zobowiązaniu z kwietnia 2019 r., W którym jnthn napisał:

Ostatnio typy, które były celem reblessoperacji, zaczęły być jawnie tworzone jako typy docelowe mixin, aby pomóc w optymalizacji. ...

W komentarzu 11 dni temu zamykającym problem rakudo GH „Rebless do niestandardowego typu już nie działa” , napisał:

Będziesz musiał ustawić przekazanie is_mixinnazwanego argumentu do ClassHOW.new_type... Nie ma możliwości zrobienia tego ze składnią klasy, dlatego też typ docelowy Rebbless musi być złożony również za pomocą MOP.

(Kliknij powyższy link, aby zobaczyć, jak to zrobić.)

Zagadnienie to jest również omówione nieco dalej, ponieważ zadziałało ... nagle nie ... dokumentacja ... powinna udokumentować poniższą sekcję wywołania .

Arne: ma pracować z klasami odziedziczonymi. Tak przynajmniej było.

pieczeń - w R epository O Fll s Pec t EST - określa, jaki kod Raku ma zrobić. (The st z roa st można odczytać jako y upposed t O a).

W innej wiadomości z kwietnia 2019 r. Jnthn napisał:

Nie było poprzedniej specyfikacji dla Metamodel::Primitives.rebless. Mam dodało ten spectest tak, że teraz nie ma. Oznacza to, że istnieje teraz pewna definicja tego, co może działać.

Fakt, że zachowanie Rakudo jest określone przez wykonywalny pakiet testowy, jest podstawową częścią podejścia @ Larry'ego do zapewnienia, że ​​Raku zachowuje się niezawodnie [1] i ma głębokie implikacje [2] .

Wpływ tej zmiany na szeroko stosowany moduł

Oto migawka wpływu tej zmiany na popularny moduł Inline :: Perl5.

W kwietniu 2019 r. NinerInline::Perl5 otworzył problem rakudo GH dotyczący wpływu, a poniżej wyodrębniłem niektóre najważniejsze informacje o wymianie między niner i jnthn.

(Pomyślałem o rzeczach, które były ważne w oryginalnym kontekście, ale rozpraszałem w kontekście tego SO. Nie zakładaj, że masz pełne zrozumienie oryginalnej rozmowy z tego wyciągu. W razie wątpliwości kliknij link. )

niner: TBH, co tu robię, pewnie zawsze było trochę podejrzane ... Mógłby nawet tego ... Mogę się go pozbyć ... Byłoby miło, gdyby nadal działały wdrożone wersje Inline :: Perl5 .

jnthn: Nie było wcześniejszej specyfikacji Metamodel::Primitives.rebless. Dodałem [a] spektakl, aby teraz był. Oznacza to, że istnieje teraz pewna definicja tego, czego można się spodziewać i na której Inline :: Perl5 może polegać.

Ponieważ nieznane nazwane parametry są ignorowane, ale :mixinnie były wymagane w poprzednich wersjach Rakudo, możliwe byłoby stworzenie nowej wersji Inline :: Perl5, która może działać zarówno na poprzednich wersjach Rakudo, jak i na nadchodzącej, więc przynajmniej może być kompatybilność wsteczna.

Nie sądzę, żeby istniał jakiś sposób na utrzymanie działania istniejących wersji Inline :: Perl5 ...

niner: Niestety przekazywanie :mixinnie pomaga w tym przypadku, ponieważ rebless odbywa się na podklasie tej utworzonej przez Metamodel::Primitives.create_type. Podklasa używa normalnej Perl6::ClassHOW.

Pracuję nad dużym refaktorem, aby w pierwszej kolejności pozbyć się bezlitosnego hacka. Ponownie otwieram ten problem, aby menedżer wydań wiedział, że nie ma działającego Inline :: Perl5 na kandydacie do wydania rakudo.

jnthn: Czy tworzysz tę klasę za pomocą MOP? Możesz przejść :is_mixindo, Perl6::ClassHOW.new_typejeśli tak.

niner: Nie, to dla tej sytuacji:class Bar is Foo { }

Pomoc z dokumentami

W komentarzu poniżej tej odpowiedzi napisałeś:

Mogę pomóc z częścią dokumentacji

To brzmi dla mnie jak bardzo odpowiednia i przydatna odpowiedź na problem w sercu twojego SOQ. Mam nadzieję, że mamy szczęście, że tak się stanie.

jeśli to pomoże

Imo twoje techniczne pisanie jest doskonałe, więc mam nadzieję, że końcowy efekt współpracy z innymi osobami zaangażowanymi w jego ulepszanie byłby cudowny.

Podstawowe ograniczenia dotyczące zawartości docs.raku.org

Dużą częścią powodu, dla którego napisałem resztę tej bardzo obszernej odpowiedzi na tak pozornie proste pytanie, i przywróciłem ją po początkowym usunięciu, gdy Jonathan na nią odpowiedział, było omówienie zasad i praktyki podejścia TDD, które leży u podstaw pracy język programowania Raku i powiązane artefakty, takie jak kompilator Rakudo i zawartość docs.raku.org .

Aiui, pożądany związek między tym, jak rzeczy mają działać w Raku, a tym, jak faktycznie działają w Rakudo, a tym, jak rzeczy powinny być dokumentowane na docs.raku.org sprowadza się do:

  • Wszystko NALEŻY zakładać, że na zawsze podlega fundamentalnej naturze projektu wolontariackiego; oraz w ramach tego ograniczenia:

  • Zachowanie w pieczeniu POWINNY być udokumentowane, a inne zachowanie NIE POWINIEN.

(Biorąc pod uwagę dostępny czas ochotnika, zainteresowanie i konsensus, od czasu do czasu zdarzają się wyjątki w celu udokumentowania zachowania Rakudo o odpowiedniej jakości, który nie jest objęty pieczeniem. W obecnej praktyce wydaje się to oznaczać zachowanie wersji Rakudo w wydanej Gwiazdie Rakudo.)

Bezużyteczna dokumentacja

Dokumentacja nie jest pomocna

Uznałem to za uczciwy komentarz. Biorąc to wszystko pod uwagę, dokumentacja, jaka była podczas pisania pytania, nie była pomocna.

dokumentacja była bezużyteczna [w 2018 r.]

To jest zupełnie inne stwierdzenie.

W reblesstym czasie nie było żadnego wejścia do pieczeni .

Jeśli strona docs.raku.org na rebless miał opisano jego zachowanie, jak to było w 2018 roku, wtedy to byłoby gorzej niż bezużyteczne , ponieważ byłoby to błędnie sugerować, że wtedy prąd zachowanie było obsługiwane. W rzeczywistości istniała możliwość złamania przyszłej wersji Rakudo bez uzasadnionej perspektywy, że zachowanie z 2018 r. Zostanie przywrócone przez głównych programistów. I rzeczywiście tak się stało: jego nieobsługiwane zachowanie z 2018 r. Pękło i nie zostało przywrócone.

Biorąc pod uwagę konsensus co do tego, co należy do docs.raku.org, a co nie (patrz wyżej), najbardziej pomocną rzeczą, jaką reblessmoże zrobić jego strona, jest albo nie dokumentowanie reblesswcale, albo, być może lepiej, założenie strony, ale upewnij się, że nie opisał swojego zachowania. Tak wyglądała sytuacja: strona istniała; nie był bezpośrednio pomocny; i to było prawdopodobnie lepsze niż nic.

(Łatwo jest sobie wyobrazić, że sytuacja jest jeszcze lepsza. Na przykład, co jeśli strony dokumentujące funkcje zawierały procent dokumentujący stan pokrycia testowego związanego z tą funkcją w wersji Rakudo w najnowszej Rakudo Star? 0% mogłoby natychmiast wskazać czytelnikowi w świadomości, że ta funkcja nie była objęta pieczeniem. To powiedziawszy, chociaż ta funkcja doc jest łatwa do wyobrażenia , kto ją wdroży? Równie łatwo jest wyobrazić sobie, że zajęłoby to rok kalendarzowy lub więcej starannej pracy i współpracy w celu użytecznego wdrażania i wdrażania, a ludzie uważają, że inne rzeczy są ważniejsze).

zadziałało ... nagle nie zadziałało ... dokumentacja ... powinna udokumentować połączenie

zadziałało

To było „szczęście”, że zadziałało.

nagle przestało to działać

Ponieważ Rakudo zostało ulepszone.

dokumentacja ... powinna udokumentować połączenie

Jak wyjaśniono wcześniej, aiui obecny konsensus Wspólnoty i / lub praktyką jest: dokumentacja POWINIEN dokumentują konkretną wersję połączenia, czyli pieczeń „zachowania D dla wersji Rakudo w najnowszej Rakudo Gwiazda; i MOŻE zachowywać dokument w innych wersjach.

i nie odnoszą się do czegoś innego

Aiui, obecny konsensus i / lub praktyka robocza jest taka, że ​​to, co niektórzy mogą uznać za „słaby” wkład doktora, np. Niektóre krótkie, pośpiesznie napisane treści i / lub linki poza dokumentami, MOGĄ zostać wprowadzone, jeśli wolontariusze uważają, że uzasadniona jest natychmiastowa zmiana w celu odzwierciedlenia pewne obawy zgłaszane przez użytkownika (np. niniejsze pisemne zgłoszenie zastrzeżeń) i fakt, że wprowadzenie „słabej” zmiany byłoby lepsze niż nic nie robienie. Możesz oczywiście zrobić PR, aby go poprawić (lub cofnąć, jeśli naprawdę uważasz, że zmiana jest tak „słaba”, że pogarsza sytuację).

moje obliczenia odnoszą się do zmian w 2019.11

(Coś takiego też jest według moich obliczeń, chociaż widziałem kompilator podający się za 2019.03.1 z tym samym przerwaniem w zachowaniu. [3] )

Myślę, że JJ zmienił dokumentację, a on po prostu źle zinterpretował komentarz Jnthna na temat sposobu dostosowania się do zmiany. Obecnie uważam, że to lepsze niż nic, ale czekam na aktualizację. :)

Przypisy

[1] Kilka minut po tym, jak Larry po raz pierwszy ogłosił projekt, który doprowadził do Raku w jego przemówieniu z 2000 r. „State of the Onion” :

Pytanie: Czy [Raku] ma specyfikacje?

Larry: to, co szczególnie chcemy podkreślić ... to może nie tyle specyfika [projektowania języka], co rozwinięcie naszego obecnego testu regresji ... w test sprawdzający poprawność tego, co naprawdę oznacza język, i rzeczywiście wychodzimy i badamy wszystkie zakątki i wulgaryzmy mówią: „To jest [Raku], to nie jest [Raku]”, a następnie mamy specyfikację do odczytu maszynowego. Dla mnie jest to o wiele ważniejsze niż to, co mówi werset w postaci czytelnej dla człowieka.

[2] Oczywiście pieczeń sprawdza się dobrze dla danego użytkownika, jeśli jego testy w wystarczającym stopniu zaspokoją jego potrzeby. Problem Arne pokazuje, jak dziury w zasięgu mogą być zaskakujące. Aby zapoznać się z omówieniem tych dziur w 2018 r., Zobacz Specyfikacje, wersjonowanie, zmiany i… Złamanie . Dobrą wiadomością jest to, że pieczeń to tylko wiele testów jednostkowych napisanych w Raku, aby sprawdzić, czy wyrażenia lub konstrukcje o określonych wartościach wykonują określoną czynność. Osobom i korporacjom łatwo jest zatem wnosić nowe testy, aby poprawić ich zasięg. Wszystko to jest pod kontrolą wersji (git), więc niestandardowe tagi, gałęzie i widelce downstream są opłacalne, trwałe i łatwe w zarządzaniu. (Rzeczywiście, to w jaki sposób nowe wersje językowe ( Christmas, Diwali, Eid(?), Itd.) Są zarządzane.)

[3] Widziałem próbę ponownego zbudowania nowej klasy utworzonej przy użyciu regularnej newclass is oldclassskładni, która działa (na moim laptopie) i nie działa (na repl.it) przy użyciu kompilatorów, które tak twierdzą 2019.03.1. (Najprawdopodobniej repl.it zainstalował wersję kodu źródłowego kompilatora lub skompilowaną z niego wersję binarną, pobraną z głowicy głównej wkrótce po zaktualizowaniu wersji kompilatora 2019.03.1, z przełomową zmianą. Zauważam, że repl.it nie ma ' t opublikował swoje internetowe repliki raku - odkryłem to przez przypadek - więc nie ma nic złego w tej sytuacji, ale wzmocniło to dla mnie potrzebę zastosowania $RAKU.compiler.verbose-configmetody zastosowanej w przetworzonych / uszkodzonych wyjściach, które właśnie połączyłem.)

raiph
źródło
Znalazłem ten artykuł, gdy próbowałem dowiedzieć się, jak działa „rebless”, ponieważ dokumentacja była bezużyteczna: stackoverflow.com/questions/44486985/... I wtedy zadziałało. A potem nagle przestało działać, a dokumentacja wciąż była bezużyteczna. Nadal jest, tak jak powinien dokumentować połączenie, a nie odnosić się do czegoś innego. A moje odniesienie do zmian w 2019.11 jest o 7 miesięcy wolne.
Arne Sommer
Mogę pomóc z częścią dokumentacji, jeśli to pomoże.
Arne Sommer
@ArneSommer Proszę zobaczyć nowe sekcje w mojej odpowiedzi, zaczynając od Pomaganie w dokumentacji .
raiph