This works:
(require 'clojure-mode)
(when (member 'clojure-mode my-packages)
(define-clojure-indent
(-> 1)
(->> 1)))
This gives the error Wrong type argument: listp, 1
:
(when (member 'clojure-mode my-packages)
(require 'clojure-mode)
(define-clojure-indent
(-> 1)
(->> 1)))
Here's what I think is happening in the second version:
define-clojure-indent
is a macro defined byclojure-mode
, which is not loaded by default. Sodefine-clojure-indent
is only defined after(require 'clojure-mode)
is evaluated.- Since both the
require
and thedefine-clojure-indent
call are in the same top-level form, all macroexpansion happens before any evaluation happens. This appears to be similar to the Gilardi scenario from Clojure. - Both
->
and->>
are macros defined bydash.el
, which I also had loaded. They have the behavior that both of the forms(-> 1)
and(->> 1)
expand to just1
. It appears that since Emacs does its macroexpansion on the
define-clojure-indent
form before it has loadedclojure-mode
, it does not yet know thatdefine-clojure-indent
is actually a macro. Therefore, it goes ahead and macroexpands recursively, transforming(define-clojure-indent (-> 1) (->> 1))
to
(define-clojure-indent 1 1)
by interpreting
->
and->>
as macros instead of simply unevaluated symbols.When
clojure-mode
is actually loaded anddefine-clojure-indent
is invoked as a macro, it throws an error because it expects its arguments to be lists, not integers.
Whereas in the first version, since the require
and define-clojure-indent
are in different top-level forms, by the time Emacs gets to macroexpanding the define-clojure-indent
form, it already knows that define-clojure-indent
is a macro, and doesn't try to do macroexpansion on its arguments. So (-> 1)
and (->> 1)
are passed to define-clojure-indent
as lists of symbols, as I would expect, and everything works.
So here is my question. If Emacs doesn't know whether or not something is a macro, why would it do macroexpansion on the arguments? In this situation, it clearly produces unintended behavior. As far as I know, this would never happen in the Clojure macro system. And I can't think of any situation in which the current functionality would be desired.
Surely I am missing something here. Is there an elegant way to avoid this problem? Or do I have a fundamental misunderstanding?
(P.S. I am aware that I could use eval-after-load
. The same problem still occurs, but I used require
in the example because it was simpler. Full code—obviously not yet working, because of this and other errors—available here.)