Clojure macro to create a synonym for a function

后端 未结 2 515
后悔当初
后悔当初 2021-01-18 09:57

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 hack

2条回答
  •  独厮守ぢ
    2021-01-18 10:21

    Macros are faster now

    I have embarked on the (most assuredly foolish) task of renaming some of Clojure's core functions in one of my projects. I've been having great fun with it (fn becomes λ, loop becomes , etc.), but I found myself very curious about performance. Greg's excellent answer from five years ago is now, I think, partially wrong. I'm using Clojure 1.5.1.

    For starters:

    user=> (defn foo1 [& args] `(+ ~@args))
    #'user/foo1
    user=> (foo1 1 2 3 4)
    (clojure.core/+ 1 2 3 4)
    

    That's definitely not what you want. Moreover, it appears that now macros are definitely the fastest option. I duplicated Greg's experiments and got very different results. The times you see below are each the best of ten runs:

    user=> (def foo +)
    #'user/foo
    user=> (defn foo1 [& args] (apply + args))
    #'user/foo1
    user=> (defmacro foo2 [& args] `(+ ~@args))
    #'user/foo2
    user=> (time (dotimes [n 1000000] (+ 1 n)))
    "Elapsed time: 53.401812 msecs"
    user=> (time (dotimes [n 1000000] (foo 1 n)))
    "Elapsed time: 135.675486 msecs"
    user=> (time (dotimes [n 1000000] (foo1 1 n)))
    "Elapsed time: 494.770352 msecs"
    user=> (time (dotimes [n 1000000] (foo2 1 n)))
    "Elapsed time: 53.509264 msecs"
    

    Also, I think the difference between the methods becomes insignificant as the function does more. This is the experiment I had run originally in which I found no difference between them:

    user=> (defmacro α [& body] `(reduce ~@body))
    #'user/α
    user=> (defn β [& body] (apply reduce body))
    #'user/β
    user=> (def γ reduce)
    #'user/γ
    user=> (time (dotimes [n 10000] (reduce + (range n))))
    "Elapsed time: 5466.920266 msecs"
    user=> (time (dotimes [n 10000] (α + (range n))))
    "Elapsed time: 5474.532622 msecs"
    user=> (time (dotimes [n 10000] (β + (range n))))
    "Elapsed time: 5491.337517 msecs"
    user=> (time (dotimes [n 10000] (γ + (range n))))
    "Elapsed time: 5456.271967 msecs"
    

    Finally, what you're looking for might be defalias from clojure.contrib.def. I have no experience with it.

提交回复
热议问题