使用列表项形成一个新的交易品种

to form a new symbol using list items

假设我在 lisp 中有两个列表

(setq a '(p q))
(setq b '(1 2))

(car a) is p
(car b) is 1

现在我想定义一个符号'(test p 1) 但是如果我在下面使用

(setq c '(test (car a) (car b)))

我得到'(测试(汽车a)(汽车b)) 这是可以理解的,但我只想知道如何将那些 (car a) 替换为 p 并将 (car b) 替换为 1 并形成一个新符号 '(test p 1)

谢谢

如果你想制作一个列表,你想要的功能是list:

(list 'test (car a) (car b))`

将是列表 (test p 1)

注意quote(简写',所以'(x)等同于(quote (x)))的目的只是简单的告诉求值者后面是字面数据,不是代码。因此,在 (list 'test ...) 中,与 (list (quote test) ...) 相同,然后 quote 告诉计算器 test 被用作文字数据,而不是用作绑定的名称,类似地,'(p q) 表示 'this is a literal list with elements p and q',而 (p q) 表示 'this is a form for evaluation, whose meaning depends on what p is')

首先,setq 不应该用于未绑定的变量。您可以对已建立的变量使用 setq。同样对于全局变量,您应该使用 *earmuffs*.

(defparameter *a* '(p q))
(defparameter *b* '(1 2))
(car *a*) ; ==> p
(car *b*) ; ==> 1

报价将使用报价结构作为数据。这意味着你写 'expr 的所有内容 expr 除了逐字记录数据之外永远不会被评估。使用 cons 创建新列表。例如

;; creates/updates binding *x* to point at the newly created list (test p 1)
(defparameter *c* (cons 'test 
                        (cons (car *a*) 
                              (cons (car *b*) 
                                    '()))))

cons 是原语,但 CL 还有其他几种创建列表的方法。例如。与函数 list:

相同
;; creates/updates binding *x* to point at the newly created list (test p 1)
(defparameter *c* (list 'test (car *a*) (car *b*)))

第二种结构变得更复杂,使用 quasiquote/unquote/unquote-splice 更容易。

;; creates/updates binding *x* to point at the newly created list (test p 1)
(defparameter *c* `(test ,(car *a*) ,(car *b*)))

;; more complex example
(defmacro my-let ((&rest bindings) &body body)
  `((lambda ,(mapcar #'car bindings)
      ,@body)
    ,(mapcar #'cadr bindings)))

(macroexpand-1 '(my-let ((a 10) (b 20)) (print "hello") (+ (* a a) (* b b))))
; ==> ((lambda (a b) 
;       (print "hello") 
;       (+ (* a a) (* b b)))
;      (10 20))

请注意,这只是用 conslistappend 制作的相同结构的糖。它可能针对最少的内存使用进行了优化,因此将共享结构。例如。 `(,x b c) 在一个过程中将执行 (cons x '(b c)) 这意味着如果您创建两个版本,它们的 cdr 将是 eq 并且您应该避免改变这些部分。

要完成 tfb 的回答,您可以写

`(test ,(car a) ,(car b)

这与

完全相同
(list 'test (car a) (car b)