Alistair Collins
Alistair Collins

Reputation: 2220

clojure.core: . operator, defmacro and setMacro

In looking through the clojure.core file after the defmacro definition you come to the following code:

(. (var defmacro) (setMacro))

What does this mean and do?

Upvotes: 4

Views: 468

Answers (3)

Michał Marczyk
Michał Marczyk

Reputation: 84361

The meaning of . is as explained by Joost's and Jeremy's answers. In case you're wondering about the details of what is accomplished by this particular method call:

This basically inserts a key called :macro with the value true into the metadata map of the Var whose name is clojure.core/defmacro. The effect of this is that from this point on, if the compiler encounters the symbol defmacro in a context where it resolves to the var #'clojure.core/defmacro (#'foo is shorthand for (var foo)) -- which will normally be everywhere, though you could e.g. shadow this Var with a let-bound local variable -- it will know that it should treat it as appropriate in the case of a name of a macro.

(Which is to say, either (1) expand the macro call using the function bound to #'clojure.core/defmacro if the symbol defmacro occurs in the operator position, i.e. immediately to the right of an opening paren, or else throw an exception to complain about a macro name being mentioned in non-operator position.)

Incidentally, the Clojure compiler routinely makes this sort of use of metadata maps on Vars, e.g. to decide on the types of various objects (cf. :tag metadata) or whether to inline a function call (IIRC, :inline and :inline-arities).

Upvotes: 6

Jeremy
Jeremy

Reputation: 22435

I'll break down the entire line, as I don't know what you already know.

First, the documentation for var says:

The symbol must resolve to a var, and the Var object itself (not its value) is returned.

If we type this into a REPL we get:

user=> (var defmarco)
#'clojure.core/defmacro

Now, the . special form allows you to call methods on instances of Java objects. In this case, the setMacro method on the returned Var object is being called.

I am not familiar enough with the code to really understand what setMacro is doing, but I gather it is altering the state of the var to say that it is a macro, and not a function or something else.

Upvotes: 2

Joost Diepenmaat
Joost Diepenmaat

Reputation: 17771

(. foo (bar)) is the low-level equivalent of (.bar foo), so this calls the method setMacro on the defmacro var with no arguments.

I suspect this call marks the defmacro function/var as being a macro. In general, lots of stuff in clojure.core uses low-level tricks to bootstrap the language so while it's interesting to see how stuff is build up, it's not really a good source for idiomatic code.

Upvotes: 1

Related Questions