在clojure中有一个":until"之类的命令吗?

unj*_*nj2 4 clojure

我想执行以下嵌套操作,直到满足期限为止.是否有: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))
Run Code Online (Sandbox Code Playgroud)

ala*_*ode 9

:whilefor表达式中的短路测试.列表元素将在第一次遇到失败的测试时生成.

在你的情况下

(for [<code omitted> :while (not (= 12 (+ a b c)))] (list a b c))
Run Code Online (Sandbox Code Playgroud)

一旦发现三元组总和为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)))))
Run Code Online (Sandbox Code Playgroud)


Jon*_*nas 6

由于收益率序列,你会选择第一要素获得所需的结果:

(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))
Run Code Online (Sandbox Code Playgroud)

由于懒惰,仅计算生成列表的第一个元素,这可以通过副作用来证明:

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)
Run Code Online (Sandbox Code Playgroud)

(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))
Run Code Online (Sandbox Code Playgroud)