2

私は、clojure ハッシュマップの値が相互に参照するための何らかの方法を考え出そうとしています。概念的には、次のようなものです。

(def m {:a 1 :b 5 :c (+ (:a m) (:b m))}  ;Implies (= (:c m) 6)

もちろん、私は循環参照しているので、これは機能しませんm。私は次のようなことができます

(def m {:a 1 :b 5 :c (fn [a b] (+ a b))})
((:c m) (:a m) (:b m)) ;=> 6

しかし、それは実際には何も得られません。なぜなら、どちらをa関数bに入れるかをまだ知る必要があるからです。別の試み:

(def m {:a 1 :b 5 :c (fn [m] (+ (:a m) (:b m)))})
((:c m) m) ;=> 6

特にこのマップではありませんが、関数をマップ内部化したので、少し良くなりました。私はこのようなものでそれを修正しようとするかもしれません

(defn new-get [k m]
  (let [v-or-fn (get m k)]
    (if (fn? v-or-fn) (v-or-fn m) v-or-fn)))

(def m {:a 1 :b 5 :c (fn [m] (+ (:a m) (:b m)))})
(new-get :a m) ;=> 1
(new-get :b m) ;=> 5
(new-get :c m) ;=> 6

これが私ができる最善のことだと思います。もっと賢いものを見逃していますか?

4

4 に答える 4

1

上記のコメントで既に述べたように、let フォームを使用できます。

(def m 
  (let [a 1 b 5] 
    {:a a :b b :c (+ a b)}))

m 定義内でのみ既知の値を使用している場合は、これで問題ありません。それ以外の場合は、 @Michiel shown のように関数パラメーターを使用することをお勧めします。

PS ちなみに、通常 clojure で使用する def 内のすべてを自由に使用できます。さらに、他のフォーム内で let を砂糖の形で自由に使用できる場合もあります (ただし、これは通常の let フォームとは異なるメカニズムを使用します)。

(for [x (...) xs]
     :let [y (+ x 1)]
     ; ...
于 2013-04-12T19:34:18.280 に答える