Thoughts on Perl and Emacs, technology and writing

Clever Emacs Lisp

Here’s another clever trick. Don’t embed the data together with the logic, as I do with my directory aliases. Save it in a separate file and load it in using (read).

Okay, it’s not that clever – I do it all the time in Perl using YAML and what-not. Slightly concerning, though, is that I didn’t automatically translate the knowledge gained from Perl to lisp. What was I thinking?

Share this:

Like this:

Related

6 Responses

There’s another way to do it without the need to create a temporary buffer by modifying the load-read-function variable which “specifies an alternate expression-reading function for load and eval-region to use instead of read. The function should accept one argument, just as read does.”

It seems that what we expect for the data in the file is subtly different. In your code it treats the contents of a buffer as a string, whereas the macro i wrote treats it as a lisp expression that gets evaluated. So for my code to work you need to make sure that the contents of the file are quoted:

‘(aa bb cc dd)

instead of:

(aa bb cc dd)

If you use the latter form with my code it assume that it is a valid expression and tries to evaluate the function ‘aa’ with the rest of the list as arguments, hence the error “(void-function aa)”.

Which way is correct? I would say neither– it depends on whether or not you want the contents to be evaluated or not. The way you wrote yours is very similar to what is used to implement the directory-local variables in files.el:

(defun dir-locals-read-from-file (file)
“Load a variables FILE and register a new class and instance.
FILE is the name of the file holding the variables to apply.
The new class name is the same as the directory in which FILE
is found. Returns the new class name.”
(with-temp-buffer
(insert-file-contents file)
(let* ((dir-name (file-name-directory file))
(class-name (intern dir-name))
(variables (let ((read-circle nil))
(read (current-buffer)))))
(dir-locals-set-class-variables class-name variables)
(dir-locals-set-directory-class dir-name class-name
(nth 5 (file-attributes file)))
class-name)))