Как написать макрос LISP с двойной кавычкой в схеме
Мне нужно написать макрос 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 (не уверен, работает ли он правильно, но похоже, что эта финальная версия работает так же в guile).
0 ответов
Я придумал более короткую версию квазицитата, но все же она требует вставки символов:
(define (foo expr)
`(list ,(car expr)
(,'quasiquote ,(pair-map (lambda (a b)
`(,(symbol->string a) . (,'unquote ,b)))
(cadr expr)))))