Search code examples
listlispcommon-lispevaluationquote

(list ...) vs '(...) in Lisp


When I have a function definition make-cd and execute the function to get the wrong answer.

(defun make-cd (title artist rating ripped)
  '(:title title :artist artist :rating rating :ripped ripped))

(add-record (make-cd "Roses" "Kathy Mattea" 7 t))

(:TITLE TITLE :ARTIST ARTIST :RATING RATING :RIPPED RIPPED)

I should have used (list ...) to get a correct answer.

(defun make-cd (title artist rating ripped)
  (list :title title :artist artist :rating rating :ripped ripped))

(add-record (make-cd "Roses" "Kathy Mattea" 7 t))

(:TITLE "Roses" :ARTIST "Kathy Mattea" :RATING 7 :RIPPED T)

Why is this?


Solution

  • Lisp has symbols as a data structure. Symbols can be used as themselves - as symbols - or as variables in code.

    You need to remember the evaluation rules for quoted expressions and function calls:

    Evaluation rule for quoted expression: nothing inside a quoted expression is evaluated. The value is returned as is.

    Evaluation rule for function calls: with a function call, all arguments are evaluated left-to-right and these results passed to the function. The computation results of the function are being returned.

    Creating data:

    A quoted symbol:

    CL-USER 13 > 'foo
    FOO
    

    A quoted list. Nothing inside the quote is evaluated.

    CL-USER 14 > '(foo bar)
    (FOO BAR)
    

    A nested list, quoted.

    CL-USER 15 > '((foo bar) (foo baz))
    ((FOO BAR) (FOO BAZ))
    

    A freshly created list using the function list. The contents are symbols.

    CL-USER 16 > (list 'foo 'bar)
    (FOO BAR)
    

    A freshly created nested list:

    CL-USER 17 > (list (list 'foo 'bar) (list 'foo 'bar))
    ((FOO BAR) (FOO BAR))
    

    A freshly created list, using quoted lists as contents:

    CL-USER 18 > (list '(foo bar) '(foo bar))
    ((FOO BAR) (FOO BAR))
    

    Creating data, using variables:

    Using the function list with two variables:

    CL-USER 19 > (let ((foo 1)
                       (bar 2))
                   (list foo bar))
    (1 2)
    

    Using a backquoted list. The elements after the comma are evaluated.

    CL-USER 20 > (let ((foo 1)
                       (bar 2))
                   `(,foo ,bar))
    (1 2)
    

    Using a nested backquoted list. The elements after the comma are evaluated.

    CL-USER 21 > (let ((foo 1)
                       (bar 2))
                   `((,foo ,bar) (,foo ,bar)))
    ((1 2) (1 2))