gpt4 book ai didi

clojure - 如何摆脱嵌套的剂量

转载 作者:行者123 更新时间:2023-12-02 04:49:59 25 4
gpt4 key购买 nike

我有一个关于嵌套剂量循环的问题。在开始函数中,一旦找到答案,我将原子设置为 true,以便 :while 的外循环验证失败。然而,它似乎并没有打破它,并且循环继续进行。这是怎么回事?

我对原子、引用、代理的使用也很困惑(为什么它们的更新函数有不同的名称,而机制几乎相同?)等。在这种情况下可以使用原子作为标志吗?显然我需要一个类似变量的对象来存储状态。

(def pentagonal-list (map (fn [a] (/ (* a (dec (* 3 a))) 2)) (iterate inc 1)))


(def found (atom false))


(defn pentagonal? [a]
(let [y (/ (inc (Math/sqrt (inc (* 24 a)))) 6)
x (mod (* 10 y) 10)]
(if (zero? x)
true
false)))


(defn both-pent? [a b]
(let [sum (+ b a)
diff (- a b)]
(if (and (pentagonal? sum) (pentagonal? diff))
true
false)))

(defn start []
(doseq [x pentagonal-list :while (false? @found)]
(doseq [y pentagonal-list :while (<= y x)]
(if (both-pent? x y)
(do
(reset! found true)
(println (- x y)))))))

最佳答案

即使原子设置为 true,您的版本也无法停止运行,直到内部 doseq 完成(直到 y > x)。一旦内循环完成,它将终止外循环。当我运行它时它最终会终止。不确定您看到了什么。

您不需要两个 doseq 来执行此操作。一个 doseq 可以同时处理两个 seq。

user> (doseq [x (range 0 2) y (range 3 6)] (prn [x y]))
[0 3]
[0 4]
[0 5]
[1 3]
[1 4]
[1 5]

(对于for也是如此。)据我所知,除了throw/catch之外,没有任何机制可以“突破”嵌套doseqs ,但这相当不惯用。不过,您根本不需要原子或 doseq 来实现此目的。

(def answers (filter (fn [[x y]] (both-pent? x y))
(for [x pentagonal-list
y pentagonal-list :while (<= y x)]
[x y])))

您的代码风格非常命令式。 “循环这些列表,然后测试值,然后打印一些内容,然后停止循环。”像这样使用原子进行控制在 Clojure 中并不是很惯用。

一种更实用的方法是采用一个 seq(五边形列表)并将其包装在将其转换为其他 seq 的函数中,直到获得一个能够提供您想要的结果的 seq。首先,我使用 for 将此 seq 的两个副本转换为 y <= x 的一个 seq 对。然后我使用 filter 将该 seq 转换为过滤掉我们不关心的值的序列。

filterfor 是惰性的,因此一旦找到第一个有效值(如果您想要一个),它将停止运行。这将返回您想要的两个数字,然后您可以将它们相减。

(apply - (first answers))

或者您可以进一步将函数包装在另一个 map 中来计算差异。

(def answers2 (map #(apply - %) answers))
(first answers2)

以这种方式进行函数式编程有一些优点。 seq 被缓存(如果你像我在这里一样捕获头部),所以一旦计算出一个值,它就会记住它,从那时起你可以立即访问它。如果不重置原子,您的版本就无法再次运行,然后必须重新计算所有内容。使用我的版本,您可以(获取 5 个答案) 获取前 5 个结果,或者根据需要映射结果以执行其他操作。您可以对其进行 doseq 并打印值。等等等等

我确信还有其他(也许更好)的方法可以在不使用原子的情况下完成此操作。通常应该避免改变引用,除非在 Clojure 中 100% 有必要。

用于更改原子/代理/引用的函数名称不同可能是因为机制不同。 Refs 是同步的,并通过事务进行协调。代理是异步的。原子是同步且不协调的。它们都是“更改引用”,并且可能某种 super 功能或宏可以将它们全部包装在一个名称中,但这会掩盖它们在幕后做着截然不同的事情的事实。充分解释这些差异可能超出了 SO 帖子解释的范围,但是 http://clojure.org充分解释了差异的所有细微差别。

关于clojure - 如何摆脱嵌套的剂量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2841932/

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