Raku rebless non funziona più con le classi ereditate


9

Il codice fornito in questo thread non funziona più: come posso rinominare un oggetto in Perl 6?

Ho scritto questo pezzo di codice l'anno scorso e poi ha funzionato. Ora non:

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

Il messaggio di errore non ha senso, poiché dovrebbe funzionare con le classi ereditate. Almeno lo era.

La documentazione non è utile; https://docs.raku.org/routine/rebless


Potrebbe essere un bug di regressione. Probabilmente è meglio segnalarlo come un problema di Rakudo.
jjmerelo,

Ci sono stati alcuni cambiamenti lo scorso febbraio: github.com/perl6/nqp/blob/…
jjmerelo

Inoltre, ho aggiornato la documentazione con una nota a piè di pagina che punta a @jnthn answer docs.raku.org/type/Metamodel::Primitives . Grazie, Raiph
Jjmerelo,

Risposte:


11

dovrebbe funzionare con classi ereditate

Non avrebbe mai dovuto essere così generale. Ho progettato quell'API e l'ho implementata in primo luogo, ed è sempre stata intesa solo come un dettaglio di implementazione dei mixin.

Fino a poco tempo fa, non faceva parte della suite di test sulle specifiche del linguaggio - e quando è diventato parte di esso, aveva già la sua semantica attuale, più restrittiva. I vincoli su di esso sono importanti per motivi di prestazioni: quando sappiamo che un tipo non è quello che può essere il bersaglio di un'operazione di mixin, possiamo compilare gli accessi agli attributi di JIT su quell'oggetto in qualcosa di molto più semplice (abbiamo pagato una mossa condizionale aggiuntiva su ogni attributo accede prima della modifica e ora deve pagare solo sui tipi target di mixin).

È possibile modificare il programma originale per funzionare utilizzando il MOP per costruire la classe. In effetti, il seguente non è proprio il programma originale; Ho fatto una piccola modifica per mostrare come si possono fornire metodi nella sottoclasse come un ruolo anonimo, in modo da evitare troppa caldaia 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

Mentre questa è la correzione semanticamente diretta al programma originale, c'è un modo più breve: usa l' butoperatore Personsull'oggetto type per produrre un tipo di mixin e restituirlo, quindi modifica il suo nome a tuo piacimento:

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;

Che è comunque solo una riga in più rispetto all'originale.


constant Woman = Person but role …Non mi rendevo conto che ciò poteva essere fatto. E così, ma per la BEGINlinea, Raku quasi si stacca da solo per poter realizzare un paradigma prototipo in stile JS!
user0721090601

Ok. Grazie per la spiegazione. Spero che possa trovare la sua strada nella documentazione, poiché docs.raku.org/routine/rebless è piuttosto inutile ... Aggiornerò a breve «Beginning Raku».
Arne Sommer,

@ user0721090601 Raku supporta, citando S12: "programmazione OO sia di classe che di prototipo" . Tuttavia, se costruisci oggetti usando la classparola chiave , citando di nuovo S12: "per impostazione predefinita, gli oggetti derivati ​​dal Musupporto di un modello basato su classi abbastanza standard ... bless... chiama ... routine BUILD ... le semantiche BUILD predefinite sono ereditato da Mu". In sintesi, direi che è più preciso affermare che Raku supporta A) "deformando seriamente anche la OO basata su classi standard di torbiere con solo un paio di righe di codice" e B) "OO basata su prototipi".
Raiph,

Vedi raku-musings.com/reblessed.html per il mio punto di vista sulla rottura delle modifiche.
Arne Sommer,

5

Vedi la risposta di jnthn per una discussione autorevole su cosa è successo reblesse cosa fare al riguardo.

ha funzionato ... Ora non .. Il messaggio di errore non ha senso ... dovrebbe funzionare con classi ereditate ... Almeno lo era ... La documentazione non è utile

Questa risposta (ultra lunga!) Potrebbe valere la pena di essere letta per coloro che sono interessati a un'ulteriore discussione dei principi e della pratica dell'approccio TDD che sta alla base del lavoro sul linguaggio di programmazione Raku e sui relativi manufatti come il compilatore Rakudo e il contenuto docs.raku.org .

Questa risposta è strutturata come risposte specifiche a parti particolari della domanda originale di Arne e dei commenti che hanno scritto in risposta a una versione precedente di questa risposta. Il mio intento era di renderlo più utile ad Arne mentre, si spera, sarebbe ancora utile agli altri.

Arne: Il codice fornito in questo thread non funziona più: come posso rinominare un oggetto in Raku?

Ho aggiornato la risposta accettata a tale SO per collegarmi a questo SO.

Arne: ho scritto questo pezzo di codice l'anno scorso, e ha funzionato allora. Adesso no

La modifica rilevante è stata discussa in un impegno di aprile 2019 in cui jnthn ha scritto:

Recentemente, i tipi che erano il bersaglio di reblessun'operazione hanno iniziato a essere creati in modo esplicito come tipi di target mixin, per favorire l'ottimizzazione. ...

In un commento di 11 giorni fa che ha chiuso il numero di rakudo GH "Rebless a un tipo personalizzato non sembra più funzionare" , ha scritto:

Dovrai fare in modo che l' is_mixinargomento denominato venga passato a ClassHOW.new_type... Non c'è modo di farlo con la sintassi della classe, quindi il tipo di destinazione del senza-re deve essere assemblato usando anche il MOP.

(Fai clic sul link sopra per le note su come fare ciò che suggerisce.)

Questo problema è anche discusso un po 'più a fondo nel fatto che ha funzionato ... improvvisamente no ... la documentazione ... dovrebbe documentare la sezione chiamata qui sotto.

Arne: dovrebbe funzionare con classi ereditate. Almeno lo era.

arrosto - la r epository o f un ll s pec t EST - determina ciò che si suppone codice Raku a che fare. (La st di roa st può essere letto come s upposed t o s.)

In un altro messaggio di aprile 2019 jnthn ha scritto:

Non c'erano specifiche precedenti per Metamodel::Primitives.rebless. Ho aggiunto questo spettacolo in modo che ora ci sia. Ciò significa che ora esiste una definizione di cosa ci si può aspettare che funzioni.

Il fatto che il comportamento di Rakudo sia dettato da una suite di test eseguibile è una parte fondamentale dell'approccio di @ Larry per garantire che Raku si comporti in modo affidabile [1] e abbia profonde implicazioni [2] .

L'impatto di questa modifica su un modulo ampiamente utilizzato

Ecco un'istantanea dell'impatto di questa modifica che si sta svolgendo per il popolare modulo Inline :: Perl5.

Nell'aprile 2019, niner ha aperto un numero di rakudo GH sull'impattoInline::Perl5 e ho estratto alcuni punti salienti dello scambio tra niner e jnthn di seguito.

(Ho eluso alcune cose che erano importanti nel contesto originale, ma che distraevano nel contesto di questo SO. Per favore, non dare per scontato che tu abbia una completa comprensione della conversazione originale da questo estratto. In caso di dubbi, fai clic sul link. )

niner: TBH quello che faccio qui probabilmente è sempre stato un po 'sospetto ... Potrebbe anche essere che ... Posso sbarazzarmi di [it] ... Sarebbe bello comunque mantenere le versioni Inline :: Perl5 già implementate funzionanti .

jnthn: non c'erano specifiche precedenti per Metamodel::Primitives.rebless. Ho aggiunto [a] spettacolo in modo che ora ci sia. Ciò significa che ora esiste una definizione di cosa ci si può aspettare che funzioni e su cui Inline :: Perl5 può fare affidamento.

Poiché i parametri con nome sconosciuto vengono ignorati, ma :mixin non erano richiesti nelle versioni precedenti di Rakudo, sarebbe possibile creare una nuova versione Inline :: Perl5 che può funzionare con le versioni precedenti di Rakudo e con quella imminente, quindi almeno back-compat.

Non credo che ci sia alcun modo per far funzionare le cose per le versioni Inline :: Perl5 esistenti ...

niner: sfortunatamente passare :mixinnon aiuta in questo caso poiché il rebless viene eseguito su una sottoclasse di quella creata via Metamodel::Primitives.create_type. La sottoclasse utilizza il normale Perl6::ClassHOW.

Sto lavorando su un grande refattore per sbarazzarsi dell'hacking ribelle in primo luogo. Sto riaprendo questo problema, quindi il responsabile del rilascio è consapevole del fatto che Inline :: Perl5 non funziona sul candidato al rilascio di rakudo.

jnthn: crei quella classe usando il MOP? Puoi passare :is_mixina in Perl6::ClassHOW.new_typetal caso.

niner: No, è per questa situazione:class Bar is Foo { }

Aiutare con i documenti

In un commento sotto questa risposta hai scritto:

Posso aiutarti con la parte relativa alla documentazione

Mi sembra una risposta molto appropriata e utile al problema alla base del tuo SOQ. Spero che siamo abbastanza fortunati che questo accada.

se questo aiuta

Imo la tua scrittura tecnica è eccellente, quindi spero che il risultato finale di lavorare con gli altri coinvolti nel miglioramento sia una cosa meravigliosa.

Vincoli fondamentali sul contenuto di docs.raku.org

Gran parte del motivo per cui ho scritto il resto di questa risposta molto ampia a una domanda così apparentemente semplice e l'ho ripristinata dopo averla inizialmente eliminata una volta che Jonathan gli aveva risposto, era discutere i principi e la pratica dell'approccio TDD che sta alla base del lavoro su il linguaggio di programmazione Raku e relativi artefatti come il compilatore Rakudo e il contenuto docs.raku.org .

Aiui, la relazione desiderabile tra il modo in cui le cose dovrebbero funzionare a Raku e il modo in cui funzionano effettivamente a Rakudo, e come le cose dovrebbero essere documentate su docs.raku.org si riduce a:

  • Si DEVE presumere che tutto sia per sempre soggetto alla natura fondamentale di un progetto di volontariato; e, nell'ambito di tale vincolo:

  • Il comportamento nell'arrosto DOVREBBE essere documentato e l'altro comportamento NON DOVREBBE.

(Dato il tempo disponibile, l'interesse e il consenso dei volontari, occasionalmente vengono fatte eccezioni per documentare il comportamento di un Rakudo correttamente QA che non è coperto dall'arrosto. Nella pratica attuale questo sembra significare il comportamento di una versione di Rakudo in una Rakudo Star rilasciata.)

Documentazione inutile

La documentazione non è utile

Ho considerato questo un commento equo. Tutto considerato, la documentazione com'era quando hai scritto la tua domanda non è stata utile.

la documentazione era inutile [nel 2018]

Questa è un'affermazione molto diversa.

reblessA quel tempo non vi era alcuna entrata arrosto .

Se la pagina docs.raku.org su rebless avesse descritto il suo comportamento com'era nel 2018, sarebbe stato peggio che inutile perché avrebbe erroneamente suggerito che il comportamento attuale fosse supportato. In realtà c'era la possibilità che entrasse in una versione futura di Rakudo senza una prospettiva ragionevole che il comportamento del 2018 sarebbe stato ripristinato dagli sviluppatori principali. E in effetti questo è avvenuto: il suo comportamento non supportato dal 2018 si è rotto e non è stato ripristinato.

Quindi, dato il consenso su ciò che appartiene a docs.raku.org e cosa no (vedi sopra), la cosa più utile che la sua reblesspagina potrebbe fare era o non documentare reblessaffatto o, forse meglio, includere una pagina per essa ma assicurarsi che non descriva il suo comportamento. Qual è la situazione: la pagina esisteva; non è stato direttamente utile; e quello era probabilmente meglio di niente.

(È facile immaginare che le cose stiano ancora meglio. Ad esempio, se le pagine che documentano le funzioni includessero una percentuale che documenta lo stato di copertura del test associato a quella funzione nella versione di Rakudo nell'ultima Rakudo Star? Uno 0% potrebbe immediatamente individuare un lettore nella consapevolezza che quella funzione non era coperta dall'arrosto. Detto questo, mentre questa caratteristica del documento è facile da immaginare , chi la implementerà? È altrettanto facile immaginare che potrebbe richiedere un anno solare o più di lavoro diligente e collaborazione per implementare e schierare utilmente, e quella gente pensa che le altre cose siano più importanti.)

ha funzionato ... all'improvviso non ha ... la documentazione ... dovrebbe documentare la chiamata

ha funzionato

È stata "fortuna" ha funzionato.

improvvisamente non ha più funzionato

Perché Rakudo è stato migliorato.

la documentazione ... dovrebbe documentare la chiamata

Come spiegato in precedenza, aiui l'attuale consenso e / o pratica lavorativa della comunità è: la documentazione DOVREBBE documentare una versione particolare della chiamata, ovvero il comportamento arrosto per la versione di Rakudo nell'ultima Rakudo Star; e MAGGIO documentare il comportamento in altre versioni.

e non fare riferimento a qualcos'altro

Aiui, l'attuale consenso e / o pratica lavorativa è che ciò che alcuni potrebbero considerare contributi doc "deboli", ad esempio alcuni contenuti brevi e scritti in fretta e / o collegamenti al di fuori dei documenti, POTREBBERO essere introdotti se i volontari ritengono che un cambiamento immediato sia giustificato per riflettere qualche preoccupazione sollevata da un utente (ad esempio questa SO) e che fare il cambiamento "debole" sarebbe meglio che non fare nulla. Ovviamente puoi fare un PR per migliorarlo (o ripristinarlo se ritieni davvero che un cambiamento sia così "debole" che peggiori le cose).

il riferimento alle modifiche nel 2019.11 è di 7 mesi libero dal mio conteggio

(È qualcosa del genere anche dal mio conteggio, anche se ho visto un compilatore che afferma di essere il 2019.03.1 con la stessa interruzione del comportamento. [3] )

Penso che JJ abbia apportato la modifica del documento e abbia semplicemente frainteso il commento di Jnthn su come adattarsi al cambiamento. Al momento penso che sia meglio di niente ma non vedo l'ora che tu lo aggiorni. :)

Le note

[1] Quanto segue è stato detto pochi minuti dopo che Larry aveva annunciato per la prima volta il progetto che aveva portato a Raku nel suo discorso "State of the Onion" del 2000 :

Domanda: [Raku] avrà specifiche?

Larry: ciò che vogliamo sottolineare in modo particolare ... non è forse tanto la specifica del [design del linguaggio] quanto lo sviluppo del nostro attuale test di regressione ... in un test di validazione di ciò che la lingua in realtà significa ed effettivamente uscire ed esplorare tutti gli angoli e crannies e dire: "Questo è [Raku], questo non è [Raku]", e quindi abbiamo effettivamente una specifica leggibile da una macchina. E per me questo è in realtà molto più importante di ciò che dice la verbosità nella cosa leggibile dall'uomo.

[2] Naturalmente, l'arrosto funziona bene per un determinato utente solo se i suoi test coprono sufficientemente le esigenze dell'utente. Il problema di Arne dimostra come i buchi nella copertura possano essere sorprendenti. Per la discussione di questi buchi nel 2018, vedi Specifiche, controllo delle versioni, modifiche e ... Rottura . La buona notizia è che l'arrosto è solo un sacco di unit test scritti in Raku per testare che espressioni o costrutti con valori particolari fanno una cosa particolare. Quindi è facile per gli individui o le aziende contribuire con nuovi test per migliorare la copertura dei test. Ed è tutto sotto controllo di versione (git), quindi tag downstream personalizzati, rami e fork sono vitali, sostenibili e gestibili. (In effetti, è così che nuove versioni linguistiche ( Christmas, Diwali, Eid(?), Etc.) sono gestite.)

[3] Ho visto un tentativo di rinominare una nuova classe creata usando la newclass is oldclasssintassi regolare sia funzionante (sul mio laptop) che non funzionante (su repl.it) usando compilatori che affermano di essere 2019.03.1. (Presumibilmente repl.it ha installato una versione del codice sorgente del compilatore, o un binario compilato da esso, prelevato dalla testa principale poco dopo l'aggiornamento della versione del compilatore 2019.03.1, con la modifica in atto. Noto che repl.it haven ' ho pubblicizzato il loro sostituto raku online - l'ho scoperto per caso - quindi non c'è nulla di spiacevole in questa situazione, ma ha rafforzato per me la necessità del $RAKU.compiler.verbose-configmetodo utilizzato negli output funzionanti / interrotti che ho appena collegato.)


Ho trovato questo articolo quando ho cercato di capire come funziona "rebless", poiché la documentazione era inutile: stackoverflow.com/questions/44486985/… E poi ha funzionato. E poi all'improvviso non ha più funzionato e la documentazione era ancora inutile. Lo è ancora, come dovrebbe documentare la chiamata, e non fare riferimento a qualcos'altro. E il riferimento alle modifiche nel 2019.11 è di 7 mesi libero dal mio conteggio.
Arne Sommer,

Posso aiutare con la parte della documentazione, se questo aiuta.
Arne Sommer,

@ArneSommer Si prega di consultare le nuove sezioni nella mia risposta a partire da Aiutare con i documenti .
Raiph,

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.