gpt4 book ai didi

clojure - cond-> 具有多个值

转载 作者:行者123 更新时间:2023-12-02 17:02:27 27 4
gpt4 key购买 nike

我遇到过很多情况,如果满足特定条件,则需要“更新”两个(甚至三个)值的向量,否则就不用管。示例:

(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...)

其中假设第一次计算和第二次计算返回一个向量 [val1, val2],其中可能包含更新的值。

这种代码风格不仅笨重,而且由于每次都会创建和解构向量,可能还会产生一些不必要的开销。

有人对如何使用普通 Clojure 改进此代码而不创建宏有建议吗?换句话说,我正在寻找一种用于多个值的 cond-> 。

最佳答案

为此,我们可以复制图形处理和其他用例中常见的技巧,其中函数始终接受上下文映射作为第一个参数(或者在我们的例子中,上下文向量)。尝试像下面这样重写它。请注意 args 中对 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] ... 的宏来删除一些样板文件。

关于clojure - cond-> 具有多个值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44722107/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com