2017-06-23 8 views
3

特定の条件が満たされている場合は、2つ(または3つ)の値のベクトルを「更新」する必要があります。例:おそらく更新された値とcond->複数の値を持つ

(let [val1 some-value 
     val2 some-other-value 
     [val1, val2] (if something-true 
         (first-calculation val1 val2 some-other-arg) 
         [val1, val2]) 
     [val1, val2] (if something-else-true 
         (second-calculation some-other-arg val1 val2) 
         [val1, val2]) 
     ...etc...) 

仮定が第一の計算と第2の演算は、ベクトルを返すことである[VAL1、VAL2]。

このコードスタイルは厄介なだけでなく、たびたびベクトルの作成と破棄のために不必要なオーバーヘッドがあります。

マクロを作成せずに誰かがこのコードを改善する方法について提案していますか?言い換えれば、私は多種の価値観のためにcond->を探しています。

答えて

6

これは、グラフィックス処理や、関数が常にコンテキストマップを最初のarg(または、この場合はコンテキストベクトル)として受け入れるその他のユースケースでよく見られるトリックをコピーできます。次のように書き直してみてください。 second-calculationへの引数の変化に注意してください:ここで

(defn first-calculation 
    [ctx    ; first arg is the context (vec here, usually a map) 
    some-other-arg] 
    (let [[val1 val2] ctx] ; destructure the context into locals 
     ... 
    [val1-new val2-new])) ; return new context 

(defn second-calculation 
    [ctx    ; first arg is the context (vec here, usually a map) 
    some-other-arg] 
    (let [[val1 val2] ctx] ; destructure the context into locals 
    ... 
    [val1-new val2-new])) ; return new context 

(let [ctx [some-value some-other-value] 
    (cond-> ctx 
     something-true  (first-calculation some-other-arg) 
     something-else-true (second-calculation some-other-arg) 
     ...etc...)) 

は、より具体的な例である:

(defn inc-foo [ctx amount] 
    (let [{:keys [foo bar]} ctx 
     foo-new (+ foo amount) 
     ctx-new (assoc ctx :foo foo-new)] 
     ctx-new)) 

(defn inc-bar [ctx amount] 
    (let [{:keys [foo bar]} ctx 
     bar-new (+ bar amount) 
     ctx-new (assoc ctx :bar bar-new)] 
    ctx-new)) 

(dotest 
    (loop [i 0 
     ctx {:foo 0 :bar 0}] 
    (let [{:keys [foo bar]} ctx 
      >>  (println (format "i =%2d foo =%3d bar =%3d " i foo bar)) 
      ctx-new (cond-> ctx 
        (zero? (mod i 2)) (inc-foo i) 
        (zero? (mod i 3)) (inc-bar i))] 
     (if (< 9 i) 
      ctx-new 
      (recur (inc i) ctx-new))))) 

結果と:

i = 0 foo = 0 bar = 0 
i = 1 foo = 0 bar = 0 
i = 2 foo = 0 bar = 0 
i = 3 foo = 2 bar = 0 
i = 4 foo = 2 bar = 3 
i = 5 foo = 6 bar = 3 
i = 6 foo = 6 bar = 3 
i = 7 foo = 12 bar = 9 
i = 8 foo = 12 bar = 9 
i = 9 foo = 20 bar = 9 
i =10 foo = 20 bar = 18 

おそらく(with-context [foo bar] ...ようなマクロを書くことができあなたがこれをたくさん使ったら定型文のいくつかを削除してください。

+0

質問を書くとき、私はいくつかの超巧妙なトリックが存在することを望んでいましたが、より単純なソリューションは通常よりエレガントです。マップを使用するあなたのアイデアはClojure-esqueになります。ありがとう! –

関連する問題