tags:

views:

292

answers:

1

Probably an easy one for anyone who actually knows how to write macros in any Lisp. I want to be able to define synonyms for function names. I've been copy-and-paste hacking core.clj to do this, but I don't want to be such a dunce forever! It seems obvious a macro that rewrites the call to a synoym-function into a call to the original function is the right way to do it.

+7  A: 

If I understand your question, there's an easier way: def the new symbol to the old function.

user=> (def foo +)
#'user/foo 
user=> (foo 1 2) 
3


The performance of def also outperforms the macro approach:

(defmacro foo2 [& args]
  `(+ ~@args))

foo2 is then effectively an alias for + and behaves exactly the same way (being rewritten as +) except for the restrictions that are placed on using macros where a value must be returned.

If you want the behavior of the "alias" to be exactly the same as that of the original function (callable in the same contexts as well) then you need to use def to rename the function.

user=> (def foo +)

user=> (defn foo1 [& args]
         `(+ ~@args))

user=> (defmacro foo2 [& args]
         `(+ ~@args))

user=> (time (dotimes [n 1000000] (foo 1 n)))
"Elapsed time: 37.317 msecs"

user=> (time (dotimes [n 1000000] (foo1 1 n)))
"Elapsed time: 292.767 msecs"

user=> (time (dotimes [n 1000000] (foo2 1 n)))
"Elapsed time: 46.921 msecs"
Greg Harman
I think that incurs the overhead of calling the original function, whereas a reader macro would rewrite the source code to call the original function. Or is that not the case in Clojure vs. (my understanding of) Lisp?
Al Chou
I should clarify that last comment. I believe there are two function calls if using the def solution: the synonym function foo is called, and it calls the original function +. A macro should convert the call to foo in the source code into a single call to + in the parsed code. Right?
Al Chou
I can't answer for Clojure, but for Scheme, the overhead for using `+` vs `foo` is the same--the symbol is evaluated. (def foo +) doesn't wrap `+`, it evaluates `+`, then binds that function to `foo`. There is one function call in both cases. Macros are not needed.
Nathan Sanders
@Greg Harman most of my response below is support for yours and it makes more sense to put it in your response, especially in light of this discussion. Feel free to copy whatever you like into your response and I'll eliminate mine.
Pinochle
@Nathan Sanders Thanks, apparently it's so much easier than my understanding of _On Lisp_ led me to believe.@Pinochle Thanks for the macro demonstrations as well as the performance profiling in support of Greg and Nathan.
Al Chou
@Pinochle - thanks for the additional material on timing; have worked it in (but feel free to edit)
Greg Harman