Определить макрос, который возвращает оператор выражения в схеме? - PullRequest
0 голосов
/ 04 апреля 2020

Я ищу такую ​​функциональность:

(op (+ 1 2))
; +

Кажется, я не могу понять, как это сделать, используя define-macro. Любая помощь?

Спасибо,

Редактировать:

Это особенно запутанно, потому что я могу сделать:

(car '(+ 1 2))
; +

Но если я сделаю:

(define-macro (op expr)
    (car expr))

(op '(+ 1 2))

Не работает.

1 Ответ

0 голосов
/ 04 апреля 2020

OP определил макрос op, как если бы он был функцией, но макросы Lisp не работают таким образом. Форма макроса оценивается для создания новой формы, которая заменяет исходный вызов макроса, но аргументы макроса передаются в тело макроса без оценки . Это означает, что в теле макроса op, car работает не с данными (+ 1 2), а с данными (quote (+ 1 2)).

Цель макроса op - не оцените (car expr), но для получения формы (car expr) (где expr заменяется значением аргумента макроса), который затем оценивается в REPL после того, как произошло расширение макроса. Это можно сделать либо с помощью list:

(define-macro (opl expr)
  (list 'car expr))

, либо с помощью квазиквотация :

(define-macro (opq expr)
  `(car ,expr))

Здесь обратная цитата представляет шаблон для списка, и запятая заставляет символ expr быть оцененным до его значения ((quote (+ 1 2))), и результат вставляется в список. Простой список в кавычках, например, '(car expr) будет соответствовать списку (car expr), где expr это просто символ expr. При квазиквотации ,expr оценивается как значение аргумента, предоставленного при вызове макроса, например, `(car ,expr) -> (car '(+ 1 2)). Обратите внимание, что (list 'car expr) выдает ту же форму, когда expr равен '(+ 1 2), как с (opl '(+ 1 2))

Этот синтаксис define-macro почти идентичен традиционному синтаксису defmacro Common Lisp, разница при этом с defmacro имя макроса идет перед списком формальных параметров, например, (defmacro op (expr) ;...). define-macro недоступно в стандартной схеме, но некоторые реализации схемы do поддерживают ее. Схема Guile поддерживает как defmacro, так и define-macro. Оба вышеперечисленных макро-решения работают в Guile:

scheme@(guile-user)> (opl '(+ 1 2))
$2 = +
scheme@(guile-user)> (opq '(+ 1 2))
$3 = +
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...