こんにちは、私はclojureで関数呼び出しを数えるメソッドを探しています。たとえば、どの関数が最も頻繁に呼び出されるかを調べることができます。理想的には、私はこれをユーザーに透過的にして、機能を追加しても、このプロセスを知らないか気にかけないようにしたいと思っています。どんな助けでも大歓迎です。clojureで関数を呼び出す
あなたはatom
に呼び出し回数を格納しwith-meta
を使用して関数にアクセサを添付することができ、事前 マイケル
こんにちは、私はclojureで関数呼び出しを数えるメソッドを探しています。たとえば、どの関数が最も頻繁に呼び出されるかを調べることができます。理想的には、私はこれをユーザーに透過的にして、機能を追加しても、このプロセスを知らないか気にかけないようにしたいと思っています。どんな助けでも大歓迎です。clojureで関数を呼び出す
あなたはatom
に呼び出し回数を格納しwith-meta
を使用して関数にアクセサを添付することができ、事前 マイケル
であなたに感謝:
(def sqrt
(let [n (atom 0)]
(with-meta
(fn [x]
(swap! n inc)
(Math/sqrt x))
{::call-count (fn [] @n)})))
例:
((::call-count (meta sqrt))) ;=> 0
(sqrt 0) ;=> 0.0
(sqrt 1) ;=> 1.0
(sqrt 2) ;=> 1.4142135623730951
((::call-count (meta sqrt))) ;=> 3
(sqrt 3) ;=> 1.7320508075688772
(sqrt 4) ;=> 2.0
(sqrt 5) ;=> 2.23606797749979
((::call-count (meta sqrt))) ;=> 6
この場合によっては大幅に減速することがありますが、カウントは常に正しく更新されます。なぜなら、Clojureアトムスレッドセーフです。別のアプローチは、deref
ではなくadd-watch
を使用することができますが、どちらがあなたの状況によりますか。あなたがしたい場合は、両方を使用することもできます。
call-count
関数を定義するマクロ
defcounted
と詳細離れてすることができます抽象
:
(defmacro defcounted [sym params & body]
`(def ~sym
(let [n# (atom 0)]
(with-meta
(fn ~params
(swap! n# inc)
[email protected])
{::call-count (fn [] @n#)}))))
(defn call-count [f]
((::call-count (meta f))))
(defcounted sqrt [x]
(Math/sqrt x))
例:
(call-count sqrt) ;=> 0
(sqrt 0) ;=> 0.0
(sqrt 1) ;=> 1.0
(sqrt 2) ;=> 1.4142135623730951
(call-count sqrt) ;=> 3
(sqrt 3) ;=> 1.7320508075688772
(sqrt 4) ;=> 2.0
(sqrt 5) ;=> 2.23606797749979
(call-count sqrt) ;=> 6
また、ここでは、varではなく関数自体にメタデータを添付しているので、この手法を匿名関数にも拡張できます。
明らかにdefcounted
にはdefn
の機能がほとんどないため、ユーザーにとってはあまり透明ではありません。この問題を修正するには、clojure.spec
を使用してdefn
スタイルの引数をより簡単に解析することができますが、この質問とは正反対のので、適切に行うようにしておきます。