Search code examples
lispcommon-lispclisp

to form a new symbol using list items


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


Solution

  • 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.