0

I'm working on a script that can compile multiple directories and then provide the first error to a file. Currently, I am tackling the issue of running make in multiple directories portion. I am making use of the compilation-finish-function hook in order to continue the compilation in the next directory. However, in this function, I get the following error: error in process sentinel: Symbol's value as variable is void: >

The way the following script works is as follows:

  • Currently (and unfortunately) using a globally defined DIRS symbol that stores the list of directories
  • my-compilation-finish-function operates on the DIRS list, popping the first element and setting DIRS to rest of the list
  • compile-in-dir-helper runs the make command on the new directory
  • compile-in-dir runs is the only interactive command and relies on the compilation hook to finish compilation in the rest of the directories

I need some kind of conditional in the hook, otherwise an infinite loop condition can occur with an empty directory variable is passed to the helper function indefinitely. I'm not sure why the sentinel is complaining of the condition function, however.

(setq
  DIRS
   '(
    "dir1"
    "dir2"
    "dir3"
    ))    

(defun my-compilation-finish-function (buffer desc)
;;;    (message "Buffer %s: %s" buffer desc)
;;;  (if (< (length 'DIRS) 0) 
     (cond (> (length DIRS) 0) (
;;;  (cond '(eql 1 0) (
        (setq directory (car DIRS))
        (compile-in-dir-helper directory)
        (setq DIRS (cdr DIRS)))))
(add-hook 'compilation-finish-functions 'my-compilation-finish-function)

(defun compile-in-dir-helper (dir)
  (setq make_cmd (concatenate 'string "make -j1 -C" dir))
  (compile make_cmd))

(defun compile-in-dir ()
  (interactive)
  (compile "make -j1 -C ~/dir0"))

1 Answer 1

3

You're missing parentheses around the interior of your cond expression. You also should not have the parentheses around the body forms of the condition (although this part is not what is causing your error). When fixed, your code should read:

(defun my-compilation-finish-function (buffer desc)
    (message "Buffer %s: %s" buffer desc)
     (cond ((> (length DIRS) 0) 
            (setq directory (car DIRS))
            (compile-in-dir-helper directory)
            (setq DIRS (cdr DIRS)))))

This may just be a typo on your part, but in case you'd like an explanation I've included one below. (If you were using paredit mode or lispy mode while writing your code, this may have been caused by an accidental barf and it can be fixed with a slurp).

Explanation:

As the Emacs manual says, each clause in cond has the form (condition body-forms...) where condition is the value that is evaluated to determine whether the body-forms will be evaluated.

This means that when Emacs attempts to evaluate this cond, it tries to evaluate the leftmost expression in the list for its truthiness. Since that is the > symbol, Emacs tries to look it up as a variable. However, by default the > symbol is not defined as a variable, so an error is produced. By wrapping the entire expression in parentheses, the condition being evaluated will be (> (length DIRS)) which is what you want.

After making this change, the body of your conditional would still be wrapped in unnecessary parentheses and this would cause a different error. The body forms should not be in a list but should instead be their own terms in the conditional clause. Here's an example conditional clause with 3 body forms:

(t (+ 3 2)
   (setq my-fake-var 9)
   99)
           

You may find the fact that Emacs thinks the > symbol is an invalid variable surprising, especially if you are used to Scheme or some other Lisp-1, since you know that > is bound as a function. However, in Emacs Lisp, functions and variables have different namespaces. Only the the > function is bound by default, not the variable. Seeing that Emacs is telling you that a symbol you are trying to use as a function is void as a variable is a good sign that you have made some kind of syntactical error in your code.

4
  • What does the nil do on the last line of the function?
    – NickD
    Jul 12, 2020 at 19:08
  • It is the return value of this cond clause since it it is the final expression in the clause. In other words, the value of this cond clause is always nil no matter what the other body-forms evaluate to.I put it in there because it was in the original code and tried to keep it as similar as possible. If I had formatted the code I put in this answer properly, this nil would have been on a new line.
    – D. Gillis
    Jul 12, 2020 at 22:50
  • Thank you for the complete and comprehensive answer. Yes, I'm still learning and I really appreciate the answer. I am removing the Nil that was pilot error as I didn't know which way to solve the error initially. Quick question, what is yy in your answer mean?
    – LeanMan
    Jul 21, 2020 at 2:37
  • That was a typo. I meant to write “by default”.
    – D. Gillis
    Jul 21, 2020 at 11:35

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.