Как написать макрос LISP с двойной кавычкой в ​​схеме - PullRequest
1 голос
/ 28 мая 2019

Мне нужно написать макрос lisp в схеме (пожалуйста, о гигиенических макросах, правилах синтаксиса и т. Д.), Которые будут иметь вызов функции и Alist в качестве аргумента

Я хочу, чтобы функция и макрос, вызывающие эту функцию, имели синтаксискак это:

(foo '(10 (a (lambda () (display "10")) b (lambda () (display "20"))))

или макрос без кавычек.

Мой последний код работает, но не уверен, что именно так вы и предполагаете писать функцию / макрос таким образом.Кажется, мне нужна двойная обратная цитата, но я не знаю, как это написать.(Я сейчас читаю «На губах» Пола Грэма, и он сказал, что двойная обратная кавычка очень трудна и нужна только для макросов, определяющих макросы, но, похоже, это то, что мне нужно).

(define (foo expr)
    `(list ,(car expr)
           (,(string->symbol "quasiquote") ,(pair-map (lambda (a b)
                                                        (cons (symbol->string a)
                                                              (list 'unquote b)))
                                                      (cadr expr)))))

(define-macro (bar expr)
   (foo expr))

(define xx (bar (10 (a 20 b (lambda () (display "x") (newline))))))
;; (list 10 `((a . ,20) (b . ,(lambda () (display "x") (newline))))
(define bfn (cdr (assoc "b" (cadr xx)))))
(bfn)
;; "x"

ивот определение пары-карты

(define (pair-map fn seq-list)
  "(seq-map fn list)

   Function call fn argument for pairs in a list and return combined list with
   values returned from function fn. It work like the map but take two items from list"
  (let iter ((seq-list seq-list) (result '()))
    (if (null? seq-list)
        result
        (if (and (pair? seq-list) (pair? (cdr seq-list)))
            (let* ((first (car seq-list))
                   (second (cadr seq-list))
                   (value (fn first second)))
              (if (null? value)
                  (iter (cddr seq-list) result)
                  (iter (cddr seq-list) (cons value result))))))))

с (string->symbol "quasiquote") Мне не удалось использовать двойную обратную кавычку, может ли это быть написано с двойной обратной кавычкой / квазицитатой?Как это должно выглядеть?

Я спрашиваю, можно ли написать по-другому, чтобы я мог исправить некоторые проблемы в моем собственном интерпретаторе lisp (не уверен, работает ли он правильно, но похоже, что эта окончательная версия работаетто же самое в хитрости).

1 Ответ

0 голосов
/ 05 июня 2019

Я придумал более короткую версию квазицитата, но все же она требует вставки символов:

(define (foo expr)
    `(list ,(car expr)
           (,'quasiquote ,(pair-map (lambda (a b)
                                      `(,(symbol->string a) . (,'unquote ,b)))
                                    (cadr expr)))))
...