在Clojure中实施中断 [英] Implementing break in Clojure
问题描述
如果条件匹配返回最后一个值,是否有办法打破Clojure中的循环?大多数算法从发现结果时返回结果并避免完成整个执行过程中受益。
Is there a way to break out of a loop in Clojure if a condition is matched returning the last value? Most algorithms benefit from returning a result when they find it and avoiding completing the whole execution.
比方说,我有一个从0到100的100个数字向量,我想找到数字10。一旦找到10,我想停止执行。
Let's say that I have a vector of 100 numbers ranging from 0 to 100 and I want to find the number 10. Once 10 is found I want the execution to stop.
比我的示例更简单的情况如下:
An even simpler case than my example is the following:
(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中不存在,但我觉得有些牵强。即使是这种情况,我也可以自己执行类似的事情吗?
I have searched enough and I can't find any way of implementing this. I have also found an answer here that states that what I am asking doesn't exist in Clojure but I find it a little far-fetched. Even if this is the case can I implement something like that myself?
(我是Clojure的新手。)
(I am new to Clojure.)
推荐答案
您几乎完全正确。重新格式化您的代码,我们会得到
You nearly got it right. Reformatting your code, we get
(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
,并希望该函数返回您的消息。
... where - for simplicity - I've got rid of the println
, and had the function hopefully return your message.
但是,正如您所注意到的,它不是:
But, as you've noticed, it doesn't:
(MySearch 0)
;nil
为什么?
问题在于(重复...)
在外部中, if
。
- 如果
(< y 10)
条件满足满足
时,(如果...)
和
满足(递归...)
依次执行,并返回后者
的结果。 - 最终,
y
是10
,因此当
条件失败时,因此当
时返回nil
。
- If the
(< y 10)
condition for thewhen
is met, the(if ...)
and the(recur ...)
are executed in turn, and the result of the latter returned. - Eventually,
y
is10
, so thewhen
condition fails, so thewhen
returnsnil
.
让内部如果 :
Let's move the recur inside the 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
。
Because we returned the message, we know that the function did stop executing. Otherwise it would have gone on and returned nil
.
在已安装 println
的情况下,该函数将输出消息并返回 nil
立即执行,因为它会继续执行。所以-关于它是否停止执行,您再也不明智了。
With the println
in place, the function would output the message and return nil
immediately, as it would do had it gone on executing. So - as to whether it stopped executing, you're none the wiser.
顺便说一下,作为找到牵强的 的答案,让我再试一次:
By the way, as the author of the answer you find far-fetched, let me try again:
- Clojure中没有中断声明。
-
反之亦然:
- There is no break statement in Clojure.
It's the other way round:
- 默认情况下,您跳出循环。
- 您必须使用
recurr
才能继续。
- You break out of a loop by default.
- You have to use
recur
to continue it.
recur
是对该函数的特殊递归调用(或循环
),您正在执行:
recur
is a special recursive call to the function (or loop
) you are executing:
- 其中一个是返回值。
- 据说处于尾巴位置。
- one where it is the returned value.
- It is said to be in tail position.
大多数Lisp系统会自动检测到此类呼叫-所谓的 tail呼叫。
因此,他们没有或需要像 recur
这样的构造。
Most Lisp systems detect such calls - so called tail calls - automatically.
So they don't have or need a construct like recur
.
话虽如此,Clojure 1.5引入了 reduced
:a <类似code> break 的减少结构。您可以在此处中阅读。
Having said that, Clojure 1.5 introduced reduced
: a break
-like construct for reduce. You can read about it here.
这篇关于在Clojure中实施中断的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!