Creating lists containing variables

Thu 12 June 2014 — Filed under notes; tags: elisp

I learned a bit about list creation in elisp today. Here's how you join a list of strings in elisp:

(mapconcat #'identity '("" "path" "to" "someplace") "/")

But I learned (thanks to legoscia on stackoverflow) that simply replacing an element in the list with a variable results in an error:

(let ((path "someplace"))
  (mapconcat #'identity '("" "path" "to" path) "/"))
Wrong type argument: sequencep, path

It turns out that a list constructed using a single quote includes symbols (and not the corresponding values) in the list.

(let ((path "someplace"))
  (print '("" "path" "to" path)))

("" "path" "to" path)

Instead, create the list either using the list function, or with a backquote and a comma:

(let ((path "someplace"))
  (print (list "" "path" "to" path))
  (print `("" "path" "to" ,path)))

("" "path" "to" "someplace")

("" "path" "to" "someplace")

Yikes, that second syntax is… not intuitive. It turns out that the backquote syntax exists just for this purpose:

Backquote constructs allow you to quote a list, but selectively evaluate elements of that list… The special marker ',' inside of the argument to backquote indicates a value that isn't constant. The Emacs Lisp evaluator evaluates the argument of ',', and puts the value in the list structure.

Well, that's good to know. I needed to take it a step further, because I was actually trying to store the value of a variable in an alist. Again, the familiar syntax for defining an alist stored the symbol instead of the value:

(let ((path "someplace"))
  (print '((:prologue . path))))

((:prologue . path))

Nope.

(let ((path "someplace"))
  (print (list `(:prologue . ,path))))

((:prologue . "someplace"))

Much better.