Адаптация кода UCI Lisp readmacros к общему Lisp - PullRequest
1 голос
/ 29 мая 2020

Я пытаюсь сделать общий лисп-эквивалент этой вспомогательной функции UCI Lisp / Interlisp для набора шаблонов.

(DRM /? (LAMBDA () (LIST '*VAR* (READ]

Документация выглядит следующим образом:

-Variables, which are used by the pattern matcher, start with a question mark ("?"), as in ?FOO.
-This is converted internally to (*VAR* role-name), so ?FOO becomes (*VAR* FOO).
-The DRM defines ? to convert itself to *VAR* when it is read

Это моя текущая реализация:

(set-macro-character #\? (lambda () (list '*var* (read))))

Но когда я запустил функцию сопоставления ниже:

(match (ptrans (actor ?x) (object ?x) (to (store)))
   (ptrans (actor (person)) (object (person)) (to (store))) nil)

, я получаю следующую ошибку, исходящую от функции DRM:

*** - EVAL/APPLY: too many arguments given to :LAMBDA

Верна ли моя реализация?

1 Ответ

0 голосов
/ 30 мая 2020

Макро-функции чтения должны принимать два аргумента: один для потока, из которого они могут читать исходный код, и один для символа, который вызвал их вызов. Если вы измените свою реализацию на

(set-macro-character #\? (lambda (stream char)
                           (declare (ignore char))
                           (list '*var* (read stream))))

, то любое вхождение ?x будет читаться как (*VAR* X). Обратите внимание, что это будет оценено при использовании в качестве аргумента функции, что вызовет ошибку, если VAR не является связанной функцией / макросом.

Вероятно, вы хотите, чтобы ?x читался в как '(*VAR* X) (обратите внимание на цитату), чтобы получить список в виде данных. В этом случае вам следует сделать следующее:

(set-macro-character #\? (lambda (stream char)
                           (declare (ignore char))
                           (list 'quote
                                 (list '*var* (read stream)))))

, чтобы предотвратить оценку формы, возвращаемой функцией макроса чтения.

...