"Приклик методу" ASSIGN-KEY "повинен бути об’єктом об'єкта" при використанні оператора присвоєння


10

Хеш з набраними клавішами ...

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

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

$MAP{$f1} = $f2;

видає помилку:

Заклик методу "ASSIGN-KEY" повинен бути об'єктним екземпляром типу "Hash [Foo, Foo]", а не об'єктом типу типу "Hash [Foo, Foo]". Ви забули ".new"?

Я вважаю це оманливим; що таке справжня помилка і що я повинен написати замість цього?

Я вже спробував %sigil для хеш-змінної, що також не працює.


Що вам розповідає, це те, що $ MAP - це клас; ОТТОМ, я б сказав, це роль. Вам потрібно інстанціювати це. Але дозвольте перевірити.
jjmerelo

Відповіді:


7

У тому, як ви це визначили, $MAPнасправді є роллю. Вам потрібно створити (фактично, каламбур ) це:

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

my $map = $MAP.new;

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

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

Мертвий подарунок тут полягав у тому, що класи не можна параметризувати , ролі роблять.

Також:

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

Але насправді повідомлення про помилку було досить інформативним, аж до пропозиції щодо використання .new, як я це роблю тут.

Ми можемо скоротити його до:

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

Виконуючи покарання з визначення, нам не потрібен проміжний клас $ MAP.


6

TL; DR JJ відповідь правильна, але пояснення залишило мене розгубленим. Зараз я розглядаю проблему, яку ви показали як повідомлення про помилку / помилку автоматичного вівірування та / або повідомлення про помилку 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 це помилка або досить близька до однієї.

Помилка / проблема застосовується і для масивів за тим же сценарієм:

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

Якщо це найкраще вважати notabug, то, можливо, повідомлення про помилку слід змінити. Хоча я погоджуюся з JJ, що повідомлення про помилку насправді є дійсним (коли ти розумієш, як працює раку, і розумієш, що відбувається), я думаю, що все-таки повідомлення про помилку LTA, якщо ми не змінимо raku (do) на dwim.

Що стосується стискаючої руки, мені не очевидно, як можна найкраще поліпшити повідомлення про помилку. І тепер ми маємо це ТАК. (див. мою думку про те, чи є ... повідомлення про помилку LTA? в останній відповіді, яку я написав .)

Ще одне рішення

Я вже спробував %sigil для хеш-змінної, що також не працює.

JJ запропонував рішення, яке ініціалізується зі значенням з явним .new. Але це скидає обмеження із змінної. Щоб зберегти його:

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

В ідеалі це constantне знадобиться, і, можливо, одного дня це не стане, але я думаю, що синтаксичний аналіз обмежений.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.