"Il chiamante del metodo 'ASSIGN-KEY' deve essere un'istanza di oggetto" quando si utilizza l'operatore di assegnazione


10

Hash con tasti digitati ...

use v6;
class Foo {}
my Hash[Foo, Foo] $MAP;

my $f1 = Foo.new;
my $f2 = Foo.new;

$MAP{$f1} = $f2;

produce l'errore:

L'invocante del metodo 'ASSIGN-KEY' deve essere un'istanza di oggetto di tipo 'Hash [Foo, Foo]', non un oggetto di tipo di tipo 'Hash [Foo, Foo]'. Hai dimenticato un '.new'?

Lo trovo fuorviante; qual è il vero errore e cosa devo scrivere invece?

Ho già provato il %sigillo per la variabile hash, che non funziona neanche.


Quello che ti sta chiamando è che $ MAP è una classe; OTOMH, direi che è un ruolo. Devi istanziarlo. Ma fammi controllare.
jjmerelo,

Risposte:


7

Nel modo in cui l'hai definito, in $MAPrealtà è un ruolo. È necessario creare un'istanza (in realtà, gioco di parole ):

class Foo {}
my Hash[Foo, Foo] $MAP;

my $map = $MAP.new;

my $f1 = Foo.new;
my $f2 = Foo.new;

$map{$f1} = $f2;
say $map;

Il regalo morto qui era che le classi non possono essere parametrizzate , i ruoli sì.

Anche:

say $MAP.DEFINITE; # False
say $map.DEFINITE; # True

Ma in realtà il messaggio di errore era piuttosto informativo, fino al suggerimento incluso .new, come faccio qui.

Possiamo accorciarlo a:

class Foo {}
my %map = Hash[Foo, Foo].new ;
%map{Foo.new} = Foo.new;
%map.say;

Effettuando il punteggio dalla definizione, non abbiamo bisogno della classe intermedia $ MAP.


6

TL; la risposta di DR JJ è giusta, ma la spiegazione mi ha lasciato confuso. Attualmente vedo il problema che hai mostrato come errore / bug di autovivificazione e / o messaggio di errore LTA.

say my Any       $Any;        # (Any)
say my Hash      $Hash;       # (Hash)
say my Hash[Int] $Hash-Int;   # (Hash[Int])
$Any<a>          = 42;        # OK
$Hash<a>         = 42;        # OK
$Hash-Int.new<a> = 42;        # OK
$Hash-Int<a>     = 42;        # must be an object instance, not a type object

Imo questo è un bug o abbastanza vicino a uno.

Un bug / problema si applica anche alle matrici nello stesso scenario:

say my Any       $Any;        # (Any)
say my Array     $Array;      # (Array)
say my Array[Int] $Array-Int; # (Array[Int])
$Any[42]           = 42;      # OK
$Array[42]         = 42;      # OK
$Array-Int.new[42] = 42;      # OK
$Array-Int[42]     = 42;      # Type check failed ... expected Array[Int] but got Array

Se è meglio considerare notabug, forse il messaggio di errore dovrebbe essere modificato. Sebbene io sia d'accordo con JJ sul fatto che il messaggio di errore sia effettivamente in questione (quando capisci come funziona raku e capisci cosa sta succedendo), penso che sia comunque un messaggio di errore LTA se non cambiamo raku (do) in dwim.

D'altra parte, non è ovvio per me come si possa migliorare al meglio il messaggio di errore. E ora abbiamo questo SO. (cfr. il mio punto al riguardo in È il ... messaggio di errore LTA? in una risposta recente che ho scritto .)

Un'altra soluzione

Ho già provato il %sigillo per la variabile hash, che non funziona neanche.

JJ ha fornito una soluzione che si inizializza con un valore con un esplicito .new. Ma questo elimina il vincolo dalla variabile. Per conservarlo:

class Foo {}
constant FooFoo = Hash[Foo:D,Foo:D];
my %foo is FooFoo;
%foo{Foo.new} = Foo.new;

Idealmente constantnon sarebbe necessario, e forse un giorno non lo sarà, ma penso che l'analisi del tratto sia limitata.

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.