«Слишком мало позиционеров» в определении макроса - PullRequest
0 голосов
/ 20 декабря 2018

Я пытаюсь создать несколько примеров использования (экспериментальных) макросов следующим образом:

use experimental :macros;
macro cards_vars() { 
  (<hearts clubs diamonds spades> X~ 1..10).map: { "my \$$^x = False;" }  
};
cards_vars(); 
say $hearts1;

Это создает и запускает макрос, а затем проверяет, существует ли одна из определенных переменных.Но я получаю эту ошибку:

Too few positionals passed; expected 3 arguments but got 2

Я даже не знаю, откуда эта ошибка.Я думаю, что это в cards_vars (), но я понятия не имею, так ли это или нет.Объявление макроса без скобок приводит к той же ошибке.

Ответы [ 2 ]

0 голосов
/ 21 декабря 2018

Обновление: Для ясности, макросы не просто экспериментальные, но очень элементарные и глючные.Подробнее об этом см. ответ Морица на другой вопрос макроса .


Давайте начнем с игры в гольф с кодом:

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.)

0 голосов
/ 20 декабря 2018

Так что немного возни и я нашел эту старую статью на Хэллоуин: https://perl6advent.wordpress.com/2012/12/23/day-23-macros/

, которая дает некоторый указатель.Вам нужно использовать quasi, чтобы выделить код, который вы собираетесь вывести.Но получить его, чтобы создать переменную?Точно сказать не могу.Я все еще настраиваюсь, если это возможно.

...