Invocant của phương thức 'ASSIGN-KEY' phải là một thể hiện đối tượng, khi sử dụng toán tử gán


10

Hash với các phím được gõ

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

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

$MAP{$f1} = $f2;

tạo ra lỗi:

Invocant của phương thức 'ASSIGN-KEY' phải là một thể hiện đối tượng của loại 'Hash [Foo, Foo]', không phải là một đối tượng loại của loại 'Hash [Foo, Foo]'. Bạn đã quên một '.new'?

Tôi thấy nó sai lệch; Thay vào đó là lỗi thực sự và tôi phải viết gì?

Tôi cũng đã thử %sigil cho biến băm, điều đó cũng không hoạt động.


Những gì nó nói với bạn là $ MAP là một lớp; OTOMH, tôi muốn nói đó là một vai trò. Bạn cần phải khởi tạo nó. Nhưng hãy để tôi kiểm tra.
jjmerelo

Câu trả lời:


7

Theo cách bạn đã định nghĩa nó, $MAPthực sự là một vai trò. Bạn cần phải khởi tạo (thực sự, chơi chữ ) nó:

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

my $map = $MAP.new;

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

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

Giveaway chết ở đây là các lớp không thể được tham số hóa , vai trò làm.

Cũng thế:

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

Nhưng trên thực tế, thông báo lỗi khá nhiều thông tin, lên đến và bao gồm cả gợi ý sử dụng .new, như tôi làm ở đây.

Chúng ta có thể rút ngắn nó xuống:

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

Bằng cách làm sáng tỏ từ định nghĩa, chúng ta không cần lớp trung gian $ MAP.


6

Câu trả lời của TL; DR JJ là đúng, nhưng lời giải thích khiến tôi bối rối. Tôi hiện đang xem sự cố mà bạn đã hiển thị dưới dạng thông báo lỗi / lỗi tự động và / hoặc thông báo lỗi 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 đây là một lỗi hoặc khá gần với một.

Một lỗi / vấn đề áp dụng cho các mảng quá trong cùng một kịch bản:

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

Nếu nó được coi là tốt nhất, thì có lẽ nên thay đổi thông báo lỗi. Mặc dù tôi đồng ý với JJ rằng thông báo lỗi thực sự là đúng (khi bạn hiểu cách raku hoạt động và tìm hiểu chuyện gì đang xảy ra), tôi nghĩ đó vẫn là một thông báo lỗi LTA nếu chúng ta không thay đổi raku (do) thành lùn.

Về mặt hấp dẫn, đối với tôi, làm thế nào một người có thể cải thiện tốt nhất thông báo lỗi. Và bây giờ chúng ta có SO này. (cf quan điểm của tôi về điều đó trong ... Thông báo lỗi LTA? trong một câu trả lời gần đây tôi đã viết .)

Giải pháp khác

Tôi cũng đã thử %sigil cho biến băm, điều đó cũng không hoạt động.

JJ đã cung cấp một giải pháp khởi tạo với một giá trị rõ ràng .new. Nhưng điều đó làm giảm các ràng buộc từ biến. Để giữ lại:

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

Lý tưởng là constantsẽ không cần thiết, và có lẽ một ngày nào đó sẽ không, nhưng tôi nghĩ rằng phân tích đặc điểm là hạn chế.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.