Обновление: Для ясности, макросы не просто экспериментальные, но очень элементарные и глючные.Подробнее об этом см. ответ Морица на другой вопрос макроса .
Давайте начнем с игры в гольф с кодом:
use experimental :macros;
macro foo { 42 }
foo
Это даетта же самая ошибка времени компиляции :
Too few positionals passed; expected 3 arguments but got 2
Эта ошибка появляется, если вы возвращаете из макроса что-либо, кроме AST
объекта. 1 Что разумно, учитывая, что это весь смысл конструкции macro
.Сообщение об ошибке менее чем удивительно, но опять же макросы являются экспериментальной функцией.
Так что вам нужно вернуть AST.Вот один из способов:
use experimental :macros;
macro foo { AST.new }
foo
Это приводит к ошибке run-time :
Useless use of constant value foo in sink context (line 3)
Это показывает, что макрос выполнил свою работу.Компилятор завершил компиляцию и перешел во время выполнения.
Явный возврат AST
объектов - неправильный путь для продолжения.Первая причина указана на странице документа AST
:
Для AST еще не определен API.Надеемся, что это станет частью работы над макросами .
Вторая причина в том, что существует конструкция более высокого уровня для создания объектов AST
, а именно конструкция quasi { ... }
3 упоминается на странице документа и Scimon:
use experimental :macros;
macro foo { quasi { 42 } }
say foo; # 42
Блок quasi
указывает компилятору компилировать вложенные операторы в форму AST.
Обратите внимание, чторезультат не AST, соответствующий блоку.Выше приведен объект AST, соответствующий 42
.
Итак, наконец, вернемся к тому, что вы пытались сделать.
Упрощение:
use experimental :macros;
macro foo { quasi { my $bar } }
foo;
say $bar
выходы:
Error while compiling ... Variable '$bar' is not declared
Принимая во внимание:
use experimental :macros;
macro foo { quasi { class bar {} } }
foo;
say bar; # (bar)
Итак, нижняя строка, лексические объявления в настоящее время не выдерживают.
Эксперимент не зашел так далеко.
Карл Мясак, создатель экспериментальных макросов в Ракудо, продолжает эксперимент в 007 .Если вы оставите вопрос в своем репозитории GH, Карл ответит.
1 Когда компилятор встречает вызов подпрограммы, которая, как он знает, является макросом 2 он заменяет вызов макроса своим результатом.Более подробно компилятор:
Компилирует все аргументы макроса в форму AST;
Вызывает макрос (во время компиляции), передавая егоаргументы в их форме AST;
Запускает подпрограмму макроса, которая должна возвращать объект AST (er, "ASTish" );
Врезает полученный объект AST (ish) в конструируемый общий AST.
Если вы не возвращаете объект AST (ish), выполняется последний шагнеправильно с сообщением об ошибке в вашем заголовке.
2 В настоящее время, если вы поместите определение макро после вызова, то компилятор не поймет, что это макрос ирассматривает это как обычную процедуру:
use experimental :macros;
say foo; # 42
macro foo { 42 }
say bar; # AST.new
macro bar { quasi { 42 } }
say bar; # 42
Вероятно, было бы лучше, если бы это вызвало ошибку во время компиляции.
3 Карл, чемпион макросов, любитслово quasi
.Он основан на наследии Лиспа, который опирается на наследие математикиПо-моему, это «слишком милый» выбор, который не очень хорош для P6.Мое обоснование заключается в том, что философия Perl предлагает выбор ключевых слов с привычным значением для новичков.Слово «квази» имеет общеизвестный нормальный английский оттенок значения «вроде, но не совсем».Это совсем не полезно.(Я предложил toAST
Карлу, но он предпочитает quasi
.)