2016-11-27 3 views
1

私は今、基本レベルでそれを理解しようとするクロージャーの初心者です。Clojureでの部分的なソースコードの明確化

私は部分的にクロージャを作成する方法を実験しており、深い理解を得るために、(source partial)を実行してソースコードを調べるべきだと思っていました。そこ

私は私が唯一の最後の2行、すなわち「可変引数」のやり方でそれを書くと同じように定義全体が冗長であることがわかり

(defn partial 
    "Takes a function f and fewer than the normal arguments to f, and 
    returns a fn that takes a variable number of additional args. When 
    called, the returned function calls f with args + additional args." 
    {:added "1.0" 
    :static true} 
    ([f] f) 
    ([f arg1] 
    (fn 
    ([] (f arg1)) 
    ([x] (f arg1 x)) 
    ([x y] (f arg1 x y)) 
    ([x y z] (f arg1 x y z)) 
    ([x y z & args] (apply f arg1 x y z args)))) 
    ([f arg1 arg2] 
    (fn 
    ([] (f arg1 arg2)) 
    ([x] (f arg1 arg2 x)) 
    ([x y] (f arg1 arg2 x y)) 
    ([x y z] (f arg1 arg2 x y z)) 
    ([x y z & args] (apply f arg1 arg2 x y z args)))) 
    ([f arg1 arg2 arg3] 
    (fn 
    ([] (f arg1 arg2 arg3)) 
    ([x] (f arg1 arg2 arg3 x)) 
    ([x y] (f arg1 arg2 arg3 x y)) 
    ([x y z] (f arg1 arg2 arg3 x y z)) 
    ([x y z & args] (apply f arg1 arg2 arg3 x y z args)))) 
    ([f arg1 arg2 arg3 & more] 
    (fn [& args] (apply f arg1 arg2 arg3 (concat more args))))) 

を取得します。

これは読みやすい機能ですか、ここで何か基本的なものがありませんか?

答えて

4

これは読みやすい機能ではなく、パフォーマンスの問題です。スチュアート・シエラはClojure Don’ts: Optional Arguments with Varargsでそれを説明した:

可変アリティ関数呼び出しは、その後、引数を保持するためのシーケンスを割り当てる適用を通過する必要があります。 Timothy Baldridgeは速くperformance comparisonを実行して、複数の固定アライメントを持つ関数への呼び出しが、可変アトリビュート(varargs)関数呼び出しよりもはるかに高速であることを示しました。そのベンチマークで

、1つの引数と可変引数バージョンは1つの引数を持つマルチアリティのバージョンよりも遅く桁の周りで、3つの引数との違いは、大きさの約2つのオーダーまで上昇。

これは、varargsをまったく使用すべきではないというわけではありません。varargsでfnを呼び出すと、パフォーマンスにはほとんど影響しませんが、タイトなループから呼び出すときには、

1

私は唯一のあなたは非常に正しいです、「可変引数」方式で

をそれを書くと同じように定義全体が冗長であることがわかりました。 varargsの定義以外はすべて冗長です。 @nbergerが指摘しているように、他のものはパフォーマンスを向上させるためにそこにあります。例えば、mapmax、およびcompのような多くのものがクロージャーのコアにあります。

関連する問題