I'm trying to make this little convenience function work:

(defun my-make-hook (when procedure)
     (let ((hook-symbol (intern (concat
                                 (substring (symbol-name when) 1)
                                 (symbol-name procedure)
       (unless (boundp hook-symbol)
         (set hook-symbol nil)
         (advice-add procedure when (lambda (&rest _) (run-hooks hook-symbol)))

But I'm getting an error that the interned symbol is void, and I believe I may actually be somehow setting the value of the symbol hook-symbol itself, rather than the symbol that hook-symbol evaluates to.

EDIT: I'm calling it with, e.g., (my-make-hook :after 'load-theme).

  • When are you getting that error? How are you calling my-make-hook? – Tyler Feb 27 '17 at 17:43
  • 1
    What @Stefan said. Alternatively, use `(lambda (&rest _) (run-hooks ',hook-symbol)). (That's a backquote before the lambda.) – Drew Feb 27 '17 at 21:25
  • Better not create any around-load-theme-hooks. – politza Feb 27 '17 at 21:28
  • @Drew, would that replace hook-symbol in the lambda with the newly created symbol (say, after-load-theme-hook) instead of making the lambda refer to the lexical variable hook-symbol? – Keith Feb 27 '17 at 21:52
  • @politza, good call. So far my use cases have been :before and :after. I haven't used any abnormal hooks. My original code threw an error if when wasn't :before or :after, but I omitted that to make the procedure more clear. – Keith Feb 27 '17 at 21:55

My crystal ball says that the above code is written in a file that does not have the magic cookie -*- lexical-binding:t -*-, and hence the let-binding of hook-symbol is dynamic rather than lexical, and by the time the advice is run, that variable doesn't exist any more, so you get a void-variable error.

Hence: place ;; -*- lexical-binding:t -*- on the first line of the file in which you wrote your function, then re-load the file, and that should hopefully fix it.

  • Thanks, @Stefan. I was only considering that (set hook-symbol nil) is evaluated inside the let form, and forgot that the lambda needs to refer back to the local variables. – Keith Feb 27 '17 at 21:45
  • For whatever reason after-load-theme-hook still isn't working, but with lexical binding the procedure works perfectly for all my other hooks. – Keith Feb 27 '17 at 21:57
  • You might like to post another question for that after-load-them-hook case, where you can give more details about "isn't working". Maybe the problem is simply that the load-theme function signals an error, so it never ends up running the "after" part. Or maybe advice-add is called after the load-theme function is called. – Stefan Feb 27 '17 at 22:28
  • It seems that setting lexical-binding to t makes the hook work, but only in the buffer where it was created. – Keith Feb 28 '17 at 12:55

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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