Встраивание функции с помощью макросов Clojure - PullRequest
11 голосов
/ 18 декабря 2010

Более любопытно, чем что-либо еще (но с ожиданием, что это иногда может быть полезным приемом для настройки производительности), возможно ли использовать макросы Clojure, чтобы «встроить» существующую функцию?Я хотел бы иметь возможность сделать что-то вроде:

(defn my-function [a b] (+ a b))

(defn add-3-numbers [a b c] 
  (inline (my-function 
    a 
    (inline (my-function 
      b 
      c)))))

и заставить его производить (во время компиляции) точно такую ​​же функцию, как если бы я сам встроил добавления, например:

(defn add-3-numbers [a b c] 
  (+ a (+ b c)))

1 Ответ

14 голосов
/ 18 декабря 2010

Если вы не знали, вы можете определить встроенные функции, используя definline

(doc definline)
-------------------------
clojure.core/definline
([name & decl])
Macro
  Experimental - like defmacro, except defines a named function whose
  body is the expansion, calls to which may be expanded inline as if
  it were a macro. Cannot be used with variadic (&) args.
nil

Также проверяя источник,

(source definline)
-------------------------
(defmacro definline
  [name & decl]
  (let [[pre-args [args expr]] (split-with (comp not vector?) decl)]
    `(do
       (defn ~name ~@pre-args ~args ~(apply (eval (list `fn args expr)) args))
       (alter-meta! (var ~name) assoc :inline (fn ~name ~args ~expr))
       (var ~name))))

definline просто определяет var с метаданными {:inline (fn definition)}. Поэтому, хотя это не совсем то, о чем вы просили, но вы можете привязать var с новыми метаданными, чтобы получить встроенное поведение.

...