如果条件匹配返回最后一个值,是否有办法打破Clojure中的循环?大多数算法从发现结果时返回结果并避免完成整个执行过程中受益匪浅。

假设我有一个100个数字的向量,范围从0到100,我想找到数字10。找到10后,我想停止执行。

比我的示例更简单的情况如下:

(defn MySearch
    [y]
    (when (< y 10)

;;Corrected. Thanks to dsm who pointed it out. Previously was (< y 5).

        (if (= (nth [1 2 3 4 5 6 7 8 9 10] y) 10)
            (println
                "I found it! Now I want to stop executing!"
            )
        )
        (recur
            (inc y)
        )
    )
)

(MySearch 0)

当我找到5时如何停止?

我已经进行了足够的搜索,但找不到任何实现此方法的方法。我在这里还找到了一个答案,指出我要问的内容在Clojure中不存在,但我觉得有些牵强。即使是这种情况,我也可以自己执行类似的操作吗?

(我是Clojure的新手。)

最佳答案

你差点说对了。重新格式化您的代码,我们得到

(defn MySearch [y]
  (when (< y 10)
    (if (= (nth [1 2 3 4 5 6 7 8 9 10] y) 10)
      "I found it! Now I want to stop executing!")
    (recur (inc y))))

...在这里-为简单起见-我摆脱了println,并希望该函数返回您的消息。

但是,您已经注意到,它没有:
(MySearch 0)
;nil

为什么?

问题在于(recur ...)if之外。这是做什么的?
  • 如果满足(< y 10)when条件,则(if ...)(recur ...)依次执行,后者的结果
    回。
  • 最终,y10,因此when条件失败,因此when返回nil

  • 让我们在if内部移动递归:
    (defn MySearch [y]
      (when (< y 10)
        (if (= (nth [1 2 3 4 5 6 7 8 9 10] y) 10)
          "I found it! Now I want to stop executing!"
          (recur (inc y)))))
    

    现在,请看:
    (MySearch 0)
    ;"I found it! Now I want to stop executing!"
    

    因为我们返回了消息,所以我们知道该函数确实停止执行。否则它将继续并返回nil

    在安装了println的情况下,该函数将输出消息并立即返回nil,就像继续执行一样。所以-关于它是否停止执行,您再也不明智了。

    顺便说一句,作为the answer you find far-fetched的作者,让我再试一次:
  • Clojure中没有break语句。
  • 相反:
  • 您默认情况下会跳出循环。
  • 您必须使用recur才能继续。
  • recur是对正在执行的函数(或loop)的特殊递归调用:
  • 其中之一是返回值。
  • 据说在尾部位置。

  • 大多数Lisp系统都会自动检测到此类调用(即所谓的尾部调用)。
    因此,他们没有或需要像recur这样的构造。

    话虽如此,Clojure 1.5引入了reduced:类似于break的reduce构造。您可以阅读有关here的信息。

    关于clojure - 在Clojure中实现休息,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/27097978/

    10-12 12:35
    查看更多