2

Clojure を学習していくうちに、次の問題にたどり着きました。

setup: addNode [id data] メンバー関数を持つdeftype、で作成されたグラフ データ構造のクラス。definterface次のように、直接呼び出されたときに期待どおりに動作します(.addNode graph "anItem" 14)

アイデア:文字列のトークン化とグラフの更新はどちらもかなりの時間を消費するため (少なくとも数百万行)、ファイルを連続して読み取ってトークン化し、トークン リストをエージェントにプッシュして、`(.addNode を実行します。グラフ ID データ) 部分。

問題:エージェントがクラス インスタンスのメンバー関数を更新関数として受け入れるようにする正しい構文が見つからないようです。

簡略化されたコード (ここでは名前空間を削除しました。タイプミスが含まれている可能性があります!):

; from graph.clj
(definterface IGraph
  (addNode [id data])
  (addNode2 [_ id data]))
(deftype Graph [^:volatile-mutable nodes] ; expects an empty map, else further calls fail horribly
  IGraph
  (addNode [this id data] (set! nodes (assoc nodes id data)) this)
  (addNode2 [this _ id data] (.addNode this id data) this))

; core.clj
(def g (Graph. {}))
(def smith (agent g))               ; agent smith shall do the dirty work

(send smith .addNode "x" 42) ; unable to resolve symbol
(send smith (.addNode @smith) "x" 42) ; IllegalArgumentException (arity?)
(send smith (.addNode2 @smith) "x" 42) ; same as above. Not arity after all?
(send smith #(.addNode @smith) "x" 42) ; ArityException of eval (3)
(send smith (partial #(.addNode @smith)) "x" 42) ; the same

; agent smith, the president is ashamed...

5 行はさまざまな理由で機能しませんが、単純な

(def jones (agent 0))
(send jones + 1)

; agent jones, this nation is in your debt

正常に実行されます。これは可能なはずですが、何が間違っていますか?

4

2 に答える 2

2

あなたの直接の問題は、それ.addNodeが関数ではなく、.特別な形式の周りに砂糖があることです。この方法で特別なフォームを渡すことはできないため、エージェントが呼び出す方法を知っている関数#(.addNode %&)または同様のものでラップする必要があります。addNode特別な形式は、すべての引数がそこにある場合にのみ評価され、グラフの最初の引数にメソッドがあることがわかります。

それでも、James Sharp の答えには良い点があります。これは、この問題を処理するための非常に必須であり、オブジェクト指向の方法です。smithこれまでのコードから、トークンをリストからwithsendにシリアルにフィードしようとしているように見えますassoc。これは古典的なreduce操作です。空のグラフをassoc取得し、その結果を取得し、その結果を取得しassoc、入力がなくなるまで、というように繰り返します。このプロセスの各ステップ間でエージェントに STM を実行させることは、あまり必要ではないようです。

^:volatile-mutableパフォーマンス上の理由で使用する場合は、トランジェントを使用して削減するassoc!か、トランジェントを処理するだけを使用することもでき(into {} ...ます (ただし、 のように動作conjし、マップではキーと値の引数を分離するのではなく、assocのベクトルを期待します)。 [key value].

于 2015-07-22T11:06:39.813 に答える