7

私は Clojure を使用しており、小規模なシミュレーションを実行する必要があります。値を保持する長さ n (n は通常 10 から 100 の間) のベクトルがあります。各シミュレーション ラウンド (おそらく 1000 ラウンド) で、ベクトル内の値の 1 つがランダムに更新されます。Java配列を使用してasetメソッドを呼び出すことでこれを行うことができると思いますが、これは関数型プログラミング/不変性の慣用句を壊します。

これを行うためのより機能的な方法はありますか、それとも Java 配列を使用する必要がありますか?

4

4 に答える 4

6
(defn run-sim [arr num-iters update-fn]
 (if (zero? num-iters)
   arr
   (let [i (rand-int (count arr))
         x (update-fn)]
     (println "setting arr[" i "] to" x)
     (recur (assoc arr i x) (dec num-iters) update-fn))))

user> (run-sim [1 2 3 4 5 6 7 8 9 10] 10 #(rand-int 1000))
setting arr[ 8 ] to 167
setting arr[ 4 ] to 977
setting arr[ 5 ] to 810
setting arr[ 5 ] to 165
setting arr[ 3 ] to 486
setting arr[ 1 ] to 382
setting arr[ 4 ] to 792
setting arr[ 8 ] to 478
setting arr[ 4 ] to 144
setting arr[ 7 ] to 416
[1 382 3 486 144 165 7 416 478 10]

ただし、必要に応じて Java 配列を使用することは恥ずべきことではありません。特に、高速化が必要な場合。配列の変更を関数の内部に制限します (入力配列を複製し、おそらくそれに取り組みます) と、賢明な人は誰もいません。

于 2009-11-17T11:55:21.433 に答える
5

ブライアンの答えに追加:さらにスピードが必要な場合は、トランジェントに頼ることもできます。

(defn run-sim
  [vektor num-iters update-fn]
  (loop [vektor    (transient vektor)
         num-iters (int num-iters)]
    (if (zero? num-iters)
      (persistent! vektor)
      (let [i (rand-int (count vektor))
            x (update-fn)]
        (recur (assoc! vektor i x) (dec num-iters))))))
于 2009-11-17T12:29:21.617 に答える
2

最初に、ベクトル内のランダムなインデックスを新しい値で更新する関数を定義しましょう。元のベクトルは変更されず、代わりに (更新された値を持つ) 新しいベクトルが返されることに注意してください。

(defn f [xs]
  (let [r (java.util.Random.)
        i (.nextInt r (count xs))
        b (.nextBoolean r)]
    (assoc xs i ((if b inc dec) (xs i)))))

この関数はインデックスを選択し、そのインデックスの値を 1 ずつ増減します。もちろん、必要に応じてこの関数を変更する必要があります。

次に、シミュレーションを実行したい回数だけ、この関数をそれ自体で構成するのは簡単なことです。

user=> ((apply comp (repeat 1000 f)) [0 0 0 0 0 0 0])
[7 -4 7 6 10 0 -6]
于 2009-11-17T12:26:29.157 に答える
1

Clojure で値を変更できないわけではありません。少し面倒なだけです。

(def vec-ref (ref my-vector))

(dosync (set! vec-ref (assoc my-vector index value))

変更されたベクトルの値を見るには、@vec-ref を使用します。

詳細がずれている可能性があります-残念ながら、私はREPLに近づいていません。しかし、それはあなたを始めるはずです。

于 2009-11-17T11:21:23.650 に答える