我无法解释为什么原子引用不保留inc的值。
1)如何纠正这个? 2)为什么在调试模式下它似乎给出了正确的值?
我知道这可能不是最佳解决方案,但想要理解为什么它不起作用。
你的任务是通过比较a0与b0,a1与b1和a2与b2来找到他们的比较点。
如果a大于b,那么Alice将获得积分。 如果a小于b,则Bob获得积分。 如果a等于b,那么两个人都不会得到一个点。
(defn compare-the-triplets
[alice bob]
(let [alice-score (atom 0)
bob-score (atom 0)]
(for [i (range 3)]
(let [a (get alice i)
b (get bob i)]
(cond
(> a b) (swap! alice-score inc)
(< a b) (swap! bob-score inc))
)) [@alice-score @bob-score]))
(compare-the-triplets [5 6 7] [3 6 10])
当我运行它时,它为Atom返回0和0。我觉得这可能不是最好的答案,但它真的很烦人为什么调试工作并获得正确值的原子,但然后他们没有正确返回。
使用let和for的范围一定不正确。
答案 0 :(得分:5)
这是冒险进入审查领域,但我认为应该强调原子在这里不是正确的工具。没有任何副作用泄漏,但是它们的使用不必要地使所有东西膨胀,并且违背了常见的功能实践。
由于这基本上只是一种减少,我认为这是最好的。你有一个集合(或者在这种情况下,有两个),需要积累一个值(或者再次,在这种情况下,两个)。无论何时出现这种情况,都应该想到reduce
:
(defn compare-the-triplets2 [alice bob]
(reduce (fn [scores [al bo]]
; If the condition on the left is true, update either the 0th or 1st score
(cond-> scores
(> al bo) (update 0 inc)
(< al bo) (update 1 inc)))
; Both start with a score of 0
[0 0]
; Zip alice and bob together, then reduce over the zipped collection
(map vector alice bob)))
关系可能会使事情复杂化,但cond->
处理得很好。不幸的是,cond->
并不像cond
那样短路,所以效率会略低一些。除非这被证明是时间关键代码,否则时差应该是可以忽略不计的。
请注意update
的使用情况,以及它与您使用swap!
的相似程度。在这种情况下,我使用0和1来指示向量累加器中的哪个得分递增。
答案 1 :(得分:1)