Guile中如何修改报价的内容

How to change content of quoted value in Guile

我有一个计算结果为 (quote ("all")) 的符号。我想将“测试”附加到列表的末尾,并得到 (quote ("all" "tests")) 但我没有找到如何:

(define make-flags ''("all"))
(append make-flags '("tests")) ; Resolves to (quote ("all") "tests")

我想我必须通过评估 make-flags 两次并重新引用它来删除引用,但我没有找到如何做。

是的,您需要先删除引号。试试这个:

(define make-flags ''("all"))
`'(,(append (cadr make-flags) '("tests")))
=> ''("all" "tests")

之所以有效,是因为 make-flags 只是这种形式的列表:(quote (quote ("all"))) 我们可以使用 carcdr 以通常的方式导航它。

第二次计算 ''("all") 得到列表 (quote ("all")) 并且它根本不是引用列表。这是 to 元素的列表,符号 quote 和列表 ("all")。如果你想向第二个元素添加一个元素,你可以通过重新创建外部列表并将第二个元素替换为具有添加元素的新列表来实现:

(define (add-second-element ele lst)
  `(,(car lst) (,@(cadr lst) ,ele) ,@(cddr lst)))
    
(add-second-element 'goofy '((donald dolly) (mickey) (chip dale)))
; ==> (donald (mickey goofy) (chip dale))

(add-second-element "tests" ''("all"))
; ==> (quote ("all" "tests")) 

如果您对 quasiquote 不太熟悉,可以不用,因为 quasiquote 只是 consappend:

的花式语法糖
(define (add-second-element-2 ele lst)
  (cons (car lst) (cons (append (cadr lst) (list ele)) (cddr lst))))

(add-second-element-2 'goofy '((donald dolly) (mickey) (chip dale)))
; ==> (donald (mickey goofy) (chip dale))

当然,如果第一个元素始终是 quote,并且只有两个元素,那么在两个版本中都可以轻松简化这些元素。