2014-10-16 43 views
2

我想跳出下面的循环,并在第10行计算结果为真时返回最小移动。我使用print语句查看了输出,并且当第10行的值为true时,它会查找我正在查找的数据,但会继续发生。在Clojure中,有一种方法可以在语句评估为真时停止循环?或者我应该使用循环以外的其他东西吗?在Clojure退出循环回路

(defn minimax [board max-mark min-mark depth best-score] 
    (loop [board board 
    max-mark max-mark 
    min-mark min-mark 
    depth depth 
    best-score best-score] 
    (if (= best-score (best-min-score board max-mark min-mark depth)) 
    (best-max-move board max-mark min-mark depth)      
    (do                
     (if (= best-score (best-min-score board min-mark max-mark depth)) 
     (best-min-move board min-mark max-mark depth)    
     (recur 
     (b/make-move-on board (remaining-scores board max-mark min-mark depth) max-mark)     
      min-mark 
      max-mark 
      (inc depth) 
      (dec best-score))))))) 
+0

只有当第二个if为false时,您的代码才会重复出现。 – 2014-10-16 19:12:46

+0

你能详细点吗?当第二个if为true时,它不返回值(最小移动板最小标记最大标记深度)。它继续进行得分动作,这让我相信它是反复出现的。 – user3245240 2014-10-16 19:16:44

+1

你怎么知道它是反复出现的?你是否声称'如果'不能像它应该那样工作?如果你的条件是真的,你的'if'将评估这两个的第一个s表达式。如果这是你正在执行的代码,除非条件为假,否则它不能重复。 – 2014-10-16 22:55:37

回答

6

关于loop

  • 这不是loop是循环:这是recur
  • loop是一个let,形成一个recur点。
  • 你不会也不会突围一个圈recur把你打成一片。

loop相当于设置和调用一个匿名函数。例如

(loop [n 5, s "Hello, world!"] 
    (if (zero? n) 
    (first s) 
    (recur (dec n) (rest s)))) 

...相当于

((fn [n s] 
    (if (zero? n) 
    (first s) 
    (recur (dec n) (rest s)))) 
5 "Hello, world!") 

随着性能的一些损失,loop可能已被编写为执行上述转换的宏。


至于你的代码:

这里有6种未定义功能。要清除汇编,我们

(declare best-min-score 
     best-max-move 
     best-min-move 
     best-max-move 
     make-move-on 
     remaining-scores) 

还有两种多余的形式。这些不会造成主动伤害,但会掩盖代码。

  • loop无需:函数本身是recur合适 目标。
  • do什么也不做:它包含一个单一的表单。

你的函数简化为

(defn minimax [board max-mark min-mark depth best-score] 
    (if (= best-score (best-min-score board max-mark min-mark depth)) 
    (best-max-move board max-mark min-mark depth) 
    (if (= best-score (best-min-score board min-mark max-mark depth)) 
     (best-min-move board min-mark max-mark depth)    
     (recur 
     (make-move-on board (remaining-scores board max-mark min-mark depth) max-mark)     
     min-mark 
     max-mark 
     (inc depth) 
     (dec best-score))))) 

而任何的未定义功能可能会反复出现,最好的办法是best-min-move

+0

谢谢!我用你的建议,并删除循环。我也将第一个if语句抽象为它自己的函数。 – user3245240 2014-10-17 17:21:52

+0

@ user3245240如果您的子功能仅在本地使用,您可以使用'let'或 - 如果它们是相互递归的 - 'letfn'来定义它们。有时你可以从上下文中提取一些参数。 – Thumbnail 2014-10-18 10:02:37