scheme中如何用双引号写LISP宏
How to write LISP macro with double quasi quotation in scheme
我需要在方案中编写 lisp 宏(请注意卫生宏和语法规则等),它将函数调用和 Alist 作为参数
我希望调用该函数的函数和宏具有如下语法:
(foo '(10 (a (lambda () (display "10")) b (lambda () (display "20"))))
或不带引号的宏。
我的最后一个代码可以正常工作,但不确定这是否是您想要像这样编写 function/macro 的方式。看来我需要双反引号但不知道怎么写。 (我现在正在阅读 Paul Graham 的 On Lips,他说双反引号非常困难,只有宏定义宏才需要,但似乎这就是我所需要的)。
(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"
这是 pair-map 的定义
(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))))))))
with (string->symbol "quasiquote")
我可以不使用双反引号,这可以用双 backquote/quasiquote 写吗?这应该是什么样子?
我在问这是否可以用不同的方式编写,这样我就可以在我自己的 lisp 解释器中解决一些问题(不确定是否工作正常,但看起来这个最终版本在诡计中工作相同)。
我想出了更短的准引用版本,但它仍然需要插入符号:
(define (foo expr)
`(list ,(car expr)
(,'quasiquote ,(pair-map (lambda (a b)
`(,(symbol->string a) . (,'unquote ,b)))
(cadr expr)))))
我需要在方案中编写 lisp 宏(请注意卫生宏和语法规则等),它将函数调用和 Alist 作为参数
我希望调用该函数的函数和宏具有如下语法:
(foo '(10 (a (lambda () (display "10")) b (lambda () (display "20"))))
或不带引号的宏。
我的最后一个代码可以正常工作,但不确定这是否是您想要像这样编写 function/macro 的方式。看来我需要双反引号但不知道怎么写。 (我现在正在阅读 Paul Graham 的 On Lips,他说双反引号非常困难,只有宏定义宏才需要,但似乎这就是我所需要的)。
(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"
这是 pair-map 的定义
(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))))))))
with (string->symbol "quasiquote")
我可以不使用双反引号,这可以用双 backquote/quasiquote 写吗?这应该是什么样子?
我在问这是否可以用不同的方式编写,这样我就可以在我自己的 lisp 解释器中解决一些问题(不确定是否工作正常,但看起来这个最终版本在诡计中工作相同)。
我想出了更短的准引用版本,但它仍然需要插入符号:
(define (foo expr)
`(list ,(car expr)
(,'quasiquote ,(pair-map (lambda (a b)
`(,(symbol->string a) . (,'unquote ,b)))
(cadr expr)))))