【问题标题】:How to write LISP macro with double quasi quotation in scheme如何在方案中编写带有双准引号的 LISP 宏
【发布时间】:2019-05-27 21:04:51
【问题描述】:

我需要在将函数调用和 Alist 作为参数的方案中编写 lisp 宏(请注意卫生宏和语法规则等)

我希望调用该函数的函数和宏具有如下语法:

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

或不带引号的宏。

我的最后一个代码正在运行,但不确定这是否是您想像这样编写函数/宏的方式。看来我需要双反引号,但不知道怎么写。 (我现在正在阅读 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))))))))

(string->symbol "quasiquote") 我不能使用双反引号,这可以用双反引号/准引号写吗?这应该是什么样子?

我在问这是否可以用不同的方式编写,以便我可以在我自己的 lisp 解释器中解决一些问题(不确定是否工作正常,但似乎这个最终版本在 guile 中的工作方式相同)。

【问题讨论】:

  • map-pair 有一个武装的if。因此pair-map 可能会返回"BaNaNa",因为未指定武装if 的行为。 (bar (10 (a 20 b (lambda () (display "x") (newline))))) 假设扩展为什么代码?
  • @Sylwester 它应该是以 car 和 Alist 作为第二项的列表,它应该扩展为 (list 10 ((a . 20) (b . (lambda () (display "x") (newline)))
  • 我想我明白了。你的意思是它扩展为(list 10 `((a . ,20) (b . ,(lambda () (display "x") (newline))) 以便 lambda 成为一个函数?
  • @Sylwester 是的,我已经编辑了问题。
  • 我不确定我是否理解这个问题,但是如果你想列出程序,你可以简单地使用quasiquote而不是使用宏。

标签: macros scheme lisp lisp-macros


【解决方案1】:

我想出了更短的准引号版本,但它仍然需要插入符号:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-06-26
    • 2011-03-08
    • 1970-01-01
    • 1970-01-01
    • 2014-10-12
    • 1970-01-01
    • 2014-12-18
    相关资源
    最近更新 更多