1

質問は私が何をしたいのかを本当に説明していませんが、他に何も考えられませんでした.

コードの外側のlet関数に空のマップと整数配列があります。整数配列を反復処理し、単純なタスクを実行し、結果のマップを外部変数の変数に追加し続けたいと考えています。

(let [a {}  ;outer variables
      b {}]
  (doseq [x [1 2 3]]
         (let [r (merge a {x (* x x)}) ;I want to append this to a
               s (merge b {x (+ x x)})] ;and this to b
           (println (str "--a--" r "--b--" s)))))

しかし、 から出るとすぐにdoseq、 myabvars はまだ空です。a と b のスコープは、doseq の内部から行われた変更を永続化するために doseq の外に拡張されず、それらは不変であることがわかりました。

このような場合、a と b の値をどのように計算すればよいでしょうか。doseq の機能を別の関数に抽出して、次のように let を呼び出してみました。

(let [a (do-that-function)])

などですが、それでも doseq ループ内のすべての変更を追跡して全体として送り返す方法を理解できませんでした。

私はこれに間違った方法でアプローチしていますか?

ありがとう


編集

本当に、私がやろうとしていることはこれです:

(let [a (doseq [x [1 2 3]] {x (* x x)})]
  (println a))

しかし、doseq は nil を返すので、a は nil になります :-s

4

2 に答える 2

3

clojure のすべての変数は不変です。変更可能な状態が必要な場合は、atomまたは refs使用する必要があります。

しかし、あなたの場合、単に からdoseqに切り替えることができますfor:

(let [a (for [x [1 2 3]] {x (* x x)})]
  (println a))

アトムで問題を解決する例を次に示します。

(let [a (atom {})
      b (atom {})]
  (doseq [x [1 2 3]]
    (swap! a assoc x (* x x))
    (swap! b assoc x (+ x x)))
  (println "a:" @a)
  (println "b:" @b))

ただし、可能な限り変更可能な状態を使用しないようにする必要があります。

(let [l [1 2 3]
      a (zipmap l (map * l l))
      b (zipmap l (map + l l))]
  (println "a:" a)
  (println "b:" b))
于 2013-07-17T11:14:18.050 に答える
1

コツは、過去のデータを変えるのではなく、既存のデータに加えて新しいデータを作るデータの流れの観点から考えることにあります。データ構造が構築されている特定の問題については、通常、reduce が使用されます。

(reduce (fn [result x] (assoc result x (* x x))) {} [1 2 3])

へへへ、「reduce」が何かを構築していることを考えると、混乱するように思えるかもしれませんが、その意味は、物の集まりが 1 つのものに「reduce」されるということです。この場合、reduce は最初に空のマップを指定します。これはバインドされて fn になり、コレクションに対する連続する各マッピングは新しい結果になり、これを assoc で再度追加します。

次のように言うこともできます。

(into {} (map (fn [x] [x (* x x)]) [1 2 3]))

あなたの質問では、単一のコレクションから一度に複数のものを作成したいと考えていました。これを行う1つの方法は次のとおりです。

(reduce (fn [[a b] x] [(assoc a x (* x x)) (assoc b x (+ x x))]) [{} {}] [1 2 3])

ここでは、構造化構文を使用して 2 つの結果構造を参照しました。[[ベクトル] を使用して] データの図を作成するだけです。reduce はまだ 1 つのもの (この場合はベクトル) しか返さないことに注意してください。

そして、それを一般化できます:

(defn xfn [n fs] 
  (reduce 
    (fn [results x] (map (fn [r f] (assoc r x (f x x))) results fs)) 
      (repeat (count fs) {}) (range n)))

=> (xfn 4 [* + -])
({3 9, 2 4, 1 1, 0 0} {3 6, 2 4, 1 2, 0 0} {3 0, 2 0, 1 0, 0 0})

結果はマップのリストです。これらの結果を構築する中間ステップを実行したい場合は、reduce を reduction に変更できます。一般に、mapコレクションを変換するreduceため、コレクションから単一の結果を構築するため。

于 2013-07-18T02:26:13.543 に答える