Я чувствую себя сбитым с толку из-за define-macro в scheme

#scheme #lisp

#схема #lisp

Вопрос:

В чем разница между двумя define-macro ниже?

 (define-macro (f x) (  x 2))
(define-macro (g x) (list '  x 2))
  

когда я вычисляю (f ( 2 3)), возникает ошибка, но вторая работает хорошо. Почему?

Комментарии:

1. как скомпилировать? какая ошибка? пожалуйста, включите полное сообщение об ошибке.

2. define-macro насколько я знаю, это не часть Scheme: вы должны указать, какую реализацию вы используете.

Ответ №1:

Макросы преобразуют код в новый код. Он делает это как можно раньше. Например. если вы используете макрос в функции, он обычно расширяется при создании этой функции задолго до выполнения кода.

(f ( 2 3)) применит функцию макроса f со значением '( 2 3) как x . Он попытается, ( '( 2 3) 2) результатом чего будет новый код, который полностью заменяет весь (f ( 2 3)) . Однако не удается добавить список к числу, поэтому нет смысла создавать подобный макрос.

(g ( 2 3)) применит функцию макроса g со значением '( 2 3) как x . Он попытается (list ' '( 2 3) 2)) получить результат ( ( 2 3) 2) . Затем это дословно помещается в расположение кода (g ( 2 3)) , как будто это всегда было ( ( 2 3) 2) до начала выполнения программы. Это работает, потому что ( ( 2 3) 2) это допустимое выражение.

Важно понимать, что макрос не вычисляет значения. Он принимает код в одном формате и создает новый код в другом. например. мы можем сделать let1

 (let1 x (  10 2)
  (  x x))
  

И это должно быть переведено на

 (let ((x (  10 2)))
  (  x x))
  

Итак, макрос:

 (define-macro (let1 name expression . body)
  `(let ((,name ,expression)) ,@body))
  

ПРИМЕЧАНИЕ: define-macro не указано ни в одной версии Scheme. Многие реализации sheme имеют defmacro и define-macro реализованы с немного другим синтаксисом и спецификацией. Код, который использует define-macro , является для этого не кодом Scheme, а диалектом, продиктованным разработчиками. Мой код был протестирован в #lang racket with (require compatibility/defmacro) , но он может не работать в вашей реализации Scheme. Единственная переносимая макросистема в Scheme — это define-syntax with syntax-rules .