Макросы теперь быстрее
Я приступил к (безусловно, глупой) задаче переименования некоторых основных функций Clojure в одном из моих проектов. Я получаю от этого огромное удовольствие (fn
становится λ
, loop
становится ⟳
и т. Д.), Но мне показалось, что мне очень интересно работать. Отличный ответ Грега от пятилетней давности теперь, я думаю, частично неверен. Я использую Clojure 1.5.1.
Для начала:
user=> (defn foo1 [& args] `(+ ~@args))
#'user/foo1
user=> (foo1 1 2 3 4)
(clojure.core/+ 1 2 3 4)
Это определенно не то, что вы хотите. Более того, похоже, что макросы сейчас, безусловно, самый быстрый вариант. Я продублировал эксперименты Грега и получил совсем другие результаты. Время, которое вы видите ниже, является лучшим из десяти пробежек:
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"
Кроме того, я думаю, что разница между методами становится незначительной, поскольку функция делает больше. Это эксперимент, который я провел изначально, в котором я не нашел никакой разницы между ними:
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"
Наконец, то, что вы ищете, может быть defalias
из clojure.contrib.def
. У меня нет опыта с этим.