Первая проблема связана с синтаксисом. Вызов функции listop анализирует список аргументов после него, начиная с термина, поэтому:
return " * " ~ callsame ~ " * ";
Группы, подобные этой:
return " * " ~ callsame(~ " * ");
И поэтому вы вызываете ~
префиксный оператор для "*", откуда исходит аргумент Str
, на который он жалуется.
Однако, в конечном счете, проблема заключается в неправильном понимании семантики композиции ролей и / или отсрочки. Рассмотрим случай не multi
:
role R { method m() { say 1; callsame() } }
class B { method m() { say 2; callsame() } }
class C is B does R { method m() { say 3; callsame(); } }
C.m
Это приводит к выводу:
3
2
Обратите внимание, что 1 никогда не достигается. Это связано с тем, что композиция ролей выравнивает : как если бы код из роли был введен в класс. Когда у класса уже есть метод с таким именем, он заменяется на тот, который в роли.
Если мы добавим multi
к каждому из них:
role R { multi method m() { say 1; callsame() } }
class B { multi method m() { say 2; callsame() } }
class C is B does R { multi method m() { say 3; callsame(); } }
C.m
Поведение сохраняется:
3
2
Поскольку компоновщик ролей учитывает длинное имя multi method
, то есть учет подписи. Так как они одинаковы, побеждает тот, кто в классе. Если бы он сохранил оба, мы получили бы исходный вызов, который привел бы к неоднозначной ошибке отправки!
Отсрочка с nextsame
, callsame
, nextwith
и callwith
- итерация всех повозможные вещи, которые мы могли бы отправить.
В случае не multi
method
это достигается путем ходьбы по MRO;поскольку метод из роли не был составлен, он не появляется ни в одном классе в MRO (ничего, что только классы появляются в MRO, поскольку роли сглаживаются во время композиции).
ВВ случае multi
method
вместо этого мы проходим набор кандидатов, которые приняли бы аргументы начальной отправки. Опять же, поскольку метод с одинаково длинным именем в классе был выбран в пользу роли один во время композиции, метод из роли просто не учитывается для отправки в первую очередь: его нет в кандидате. список proto
, и поэтому не будет отложено до.