6

In my .emacs conf file, I've got this function that adds a hook to set the compile-command based on the mode. It looks something like,

(defun set-compile-cmd (mode-hook cmd)
  (add-hook mode-hook (lambda () 
    (set (make-local-variable 'compile-command) cmd))))

But I get an error that says value of symbol cmd is void. Shouldn't cmd exist in the scope of the lambda as well?

Drew
  • 75,699
  • 9
  • 109
  • 225

1 Answers1

11

No, it shouldn't, if you use dynamic binding. Here are two choices (alternatives) that can help:

  1. Use lexical binding. Set variable lexical-binding for the file.
  2. Use dynamic binding (what you are doing now, no doubt), but also substitute the value of the variable cmd for the variable cmd in the lambda body. You can do this only if the function body of the lambda does not actually need cmd to be a variable when it is invoked and can get by with just its value (its value at the time the function is added to the hook).

For #1, see node Using Lexical Binding in the Elisp manual. Essentially, you'll have to add -*- lexical-binding: t; -*- to the end of the first line of the file.

For #2, you do this:

(add-hook mode-hook `(lambda () (set (make-local-variable 'compile-command) ',cmd))))

For information about this, see node Backquote in the Elisp manual.

In the case of #2, what is added to the hook is a textual lambda expression. It is interpreted (and so invoked) as a function only when the hook is run.

In the case of #1, the function (a closure, actually) corresponding to the lambda expression is interpreted as (understood to be) a function when it is added to the hook, and it can thus even be byte-compiled.

The closure contains a variable binding of cmd to the value it had when the function was added to the hook), as part of the function code (compiled or not).

This means that when that function is invoked any code that it runs has access to cmd as a variable at that time (not just a value). If you don't really need a variable cmd at that time and a value will do, and if you don't care about byte-compiling the lambda code, then #1 is typically adequate.

Malabarba
  • 22,878
  • 6
  • 78
  • 163
Drew
  • 75,699
  • 9
  • 109
  • 225