2010-12-18 8 views
11

Clojureマクロを使用して既存の関数をインライン化することは可能なのですか?(ただし、パフォーマンスチューニングの役に立つトリックであることが予想される)私のような、追加自分自身をインライン化したかのようにまったく同じ機能を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))) 
+0

'apply'関数を見ましたか? http://clojuredocs.org/clojure_core/clojure.core/apply – edbond

+1

は実行時に動的に適用され、コンパイル時にインライン展開を実行するものを探しています.... – mikera

+0

'(read-string(clojure.repl/source-fn \ 'my-function))'は良い出発点のようです! – vemv

答えて

14

場合、あなたは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 
を使用してインライン関数を定義することができます3210

は、ソースを調べる、

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

definlineは、単にメタデータ{:inline (fn definition)}varを定義します。だからあなたが求めていたものではありませんが、新しいメタデータでvarを再バインドして、インラインの動作を得ることができます。

+0

有用なリンク - これは間違いなく多くの状況で役に立つツールのように見えます。私が探しているものとの主な違いは、関数がインラインで明示的に定義されている必要があると思われるのに対し、任意の関数をインライン化できるようにしたいということです。 – mikera

+0

実装を検討していませんが、潜在的な解決策。 :inlineタグを含むメタデータを使って関数varを1にリビルドするマクロを書くことができます。解決しなければならない重要な問題は、実行時ではなくコンパイル時に確実に再バインドを行うことです。 – bmillare

関連する問題