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
По-моему, это ошибка или довольно близко к ней.
Ошибка / проблема применима и к массивам в том же сценарии:
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 в том, что сообщение об ошибке действительно присутствует (когда вы понимаете, как работает raku и выясняете, что происходит), я думаю, что это, тем не менее, сообщение об ошибке LTA, если мы не изменим raku (do) на dwim.
С другой стороны, для меня не очевидно, как лучше всего улучшить сообщение об ошибке. И теперь у нас есть это ТАК. (Сравните мою точку зрения на это в ... сообщении об ошибке LTA? в недавнем ответе, который я написал .)
Другое решение
Я уже пробовал %
сигил для хеш-переменной, которая тоже не работает.
JJ предоставил решение, которое инициализируется значением с явным .new
. Но это снимает ограничение с переменной. Чтобы сохранить это:
class Foo {}
constant FooFoo = Hash[Foo:D,Foo:D];
my %foo is FooFoo;
%foo{Foo.new} = Foo.new;
В идеале в constant
этом нет необходимости, и, возможно, однажды это не понадобится, но я думаю, что разбор черт ограничен.