say I have two lists in lisp
(setq a '(p q))
(setq b '(1 2))
(car a) is p
(car b) is 1
now I want to define a symbol '(test p 1) but if I use below
(setq c '(test (car a) (car b)))
I get '(test (car a) (car b)) it is understandable, but I just want to know how can I substitute those (car a) to p and (car b) to 1 and form a new symbol of '(test p 1)
Thanks
First off, setq
should not be used on unbound variables. You can use setq
on established variables. Also for global variables you should use *earmuffs*
.
(defparameter *a* '(p q))
(defparameter *b* '(1 2))
(car *a*) ; ==> p
(car *b*) ; ==> 1
The quote will use the quotes structure as data. That means everything expr
where you write 'expr
will never be evaluated beyond taking the data verbatim. New lists are created with cons
. eg.
;; 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
is the primitive, but CL has several other ways to create lists. eg. the same with the function list
:
;; creates/updates binding *x* to point at the newly created list (test p 1)
(defparameter *c* (list 'test (car *a*) (car *b*)))
The second the structure becomes more complex using quasiquote
/unquote
/unquote-splice
is a lot easier.
;; 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))
Note that this is just sugar for the identical structure made with cons
, list
, and append
. It might be optimized for minimal memory use so will share structure. eg. `(,x b c)
in a procedure will do (cons x '(b c))
which means if you create two versions their cdr
will be eq
and you should refrain from mutating these parts.