我想执行以下嵌套操作,直到满足渐进为止。 是否有:until关键字在条件匹配时停止进一步操作。?
此命令生成Pythagoran Triplet 3 4 5.一旦达到该数字序列,我不希望它做任何其他事情。
(for [a (range 1 100)
b (range 1 100)
c (list (Math/sqrt (+ (Math/pow (int a) 2) (Math/pow (int b) 2))))
:when (= 12 (+ a b c))]
(list a b c))
答案 0 :(得分:9)
:while
是for
表达式中的短路测试。列表元素将在第一次遇到失败的测试时生成。
在你的情况下
(for [<code omitted> :while (not (= 12 (+ a b c)))] (list a b c))
一旦发现三元组总和为12,就会停止生成元素。
虽然有一个问题,但它没有达到你所期望的水平。三元组本身不会成为结果的一部分,因为它失败测试。
如果您只查找单个匹配结果,列表理解可能不是最佳解决方案。为什么不直接使用循环?
(loop [xs (for [a (range 1 100)
b (range 1 100)] [a, b])]
(when (seq xs)
(let [[a, b] (first xs)
c (Math/sqrt (+ (Math/pow (int a) 2)
(Math/pow (int b) 2)))]
(if (not (= 12 (+ a b c)))
(recur (next xs))
(list a b c)))))
答案 1 :(得分:6)
由于for产生 lazy 序列,您将通过选择第一个元素获得所需的结果:
(first (for [a (range 1 100)
b (range 1 100)
c (list (Math/sqrt (+ (Math/pow (int a) 2)
(Math/pow (int b) 2))))
:when (= 12 (+ a b c))]
(list a b c))
由于懒惰,只计算生成列表的第一个元素,这可以通过副作用来证明:
user=> (first
(for [a (range 1 100)
b (range 1 100)
c (list (Math/sqrt (+ (Math/pow (int a) 2)
(Math/pow (int b) 2))))
:when (= 12 (+ a b c))]
(do (println "working...")
(list a b c))))
working...
(3 4 5.0)
(for ...)
附带一个:let修饰符,因此无需在列表中包装c:
(for [a (range 1 100)
b (range 1 100)
:let [c (Math/sqrt (+ (Math/pow (int a) 2)
(Math/pow (int b) 2)))]
:when (= 12 (+ a b c))]
(list a b c))