tags:

views:

539

answers:

3

So following on from http://stackoverflow.com/questions/1315099/clojure-macro-to-create-a-synonym-for-a-function , I discovered that def can't be used to define a synonym for a macro. Below are examples I tried that Clojure doesn't allow.

;(def def-function defn)
;(def case cond)
;(def function fn)

Is it possible to define synonyms/aliases for macros in Clojure? Would it require using defmacro?

+2  A: 

To do this, in essence, you would have to rewrite the macro exactly as the original just substituting a different name (you would of course use defmacro to do this). That's the only way this is possible since macros don't return a value, but simply write out code which is to be subsequently evaluated.

Def requires binding a name to a value rather than a block of code.

(def symbol init?)

Creates and interns or locates a global var with the name of symbol and a namespace of the value of the current namespace (ns). If init is supplied, it is evaluated, and the root binding of the var is set to the resulting value. If init is not supplied, the root binding of the var is unaffected. def always applies to the root binding, even if the var is thread-bound at the point where def is called. def yields the var itself (not its value). Throws an exception if symbol is already in the namespace and not mapped to an interned var.

from Clojure: Special Forms

Macros don't evaluate their forms:

Macros are functions that manipulate forms, allowing for syntactic abstraction. If the operator of a call is a symbol that names a global var that is a macro function, that macro function is called and is passed the unevaluated operand forms [italics mine]. The return value of the macro is then evaluated in its place.

from Clojure: Evaluation

In sum, the point of the macro is to delay evaluation, so it cannot provide a value for def to bind to a symbol.

Pinochle
Thanks for the explanation!
Al Chou
+3  A: 

You can use a macro:

user=> (defmacro def-function [& args] `(defn ~@args))
#'user/def-function
user=> (def-function g [] 2)
#'user/g
user=> (g)
2

Or you can use clojure.contrib.def/defalias:

user=> (use 'clojure.contrib.def)
nil
user=> (defalias def-function defn)
#'user/def-function
user=> (def-function g [] 2)
#'user/g
user=> (g)
2
Alex B
+7  A: 

May sound (line-)noisy but

(def #^{:macro true} case #'cond)

works!

cgrand