使用列表项形成一个新的交易品种
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))
请注意,这只是用 cons
、list
和 append
制作的相同结构的糖。它可能针对最少的内存使用进行了优化,因此将共享结构。例如。 `(,x b c)
在一个过程中将执行 (cons x '(b c))
这意味着如果您创建两个版本,它们的 cdr
将是 eq
并且您应该避免改变这些部分。
要完成 tfb 的回答,您可以写
`(test ,(car a) ,(car b)
这与
完全相同
(list 'test (car a) (car b)
假设我在 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))
请注意,这只是用 cons
、list
和 append
制作的相同结构的糖。它可能针对最少的内存使用进行了优化,因此将共享结构。例如。 `(,x b c)
在一个过程中将执行 (cons x '(b c))
这意味着如果您创建两个版本,它们的 cdr
将是 eq
并且您应该避免改变这些部分。
要完成 tfb 的回答,您可以写
`(test ,(car a) ,(car b)
这与
完全相同(list 'test (car a) (car b)