如何在clojure中实现具有嵌套返回的循环?

如何在clojure中实现具有嵌套返回的循环?,clojure,clojurescript,Clojure,Clojurescript,我在这里玩一个狡猾的教程: 我想知道如何在clojurescript/clojure中实现这个特殊的功能 var max_=5; 对于(var x=0;x

我在这里玩一个狡猾的教程:

我想知道如何在clojurescript/clojure中实现这个特殊的功能

var max_=5;
对于(var x=0;x=最大村庄){
返回;
}
}
}
}
我知道我们可以使用
(for[])
构造,但是当max_villages达到5时,如何让它停止呢?

这里有一种方法:

(def max-villages 5)

(->> (for [x (range map-width)
           y (range map-height)]
       [x y])
     (filter (fn [_] (< (rand) 0.02)))
     (take max-villages))

:当循环的测试表达式失败时,
在当前嵌套级别终止循环<代码>:当立即进入下一个迭代时
doseq
也支持分块,但是
:虽然
会阻止它执行不必要的工作。

使用递归,它可能类似于:

(letfn [(op [x y]
          (if (= (rand) 0.02)
            (do
              (village-at x y)
              (if (>= (village-length) max-villages) true))))]
  (loop [x 0 y 0]
    (when (and (< x width) (not (op x y)))
      (if (= (inc y) height)
        (recur (inc x) 0)
        (recur x (inc y))))))
(letfn[(op[x y]
(如果(=(兰特)0.02)
(做
(x y村)
(如果(>=(村庄长度)最大村庄数)为true))]
(循环[x0y0]
(当(和(
这是一个很棒的教程

Michael方法的一个变体(我刚刚对他的答案发表了评论,但我还没有足够的堆栈能力)是使用笛卡尔积,而不是嵌套for循环:

;; some stub stuff to get the example to run
(ns example.core
  (:use clojure.math.combinatorics))

(def max-villages 5)
(def map-width 10)
(def map-height 10)
(defn crafty-e [x y z] (print z))

;; the example, note I use doseq rather than map to empasize the fact that the loop 
;; is being performed for its side effects not its return value.
(doseq [coord (take max-villages 
                (filter 
                 (fn [_] (< (rand)  0.02))
                 (cartesian-product (range map-width) (range map-height))))]
(crafty-e :village :at coord))
;;一些让示例运行的存根
(ns example.core)
(:使用clojure.数学.组合数学)
(def最大值5)
(def地图宽度10)
(def地图高度10)
(defn crafty-e[x y z](打印z))
;; 注意,在这个例子中,我使用doseq而不是map来放大循环
;; 正在针对其副作用而不是返回值执行。
(doseq[coord(以最大值为准)
(过滤器
(fn[41;](<(兰特)0.02))
(笛卡尔积(范围贴图宽度)(范围贴图高度))]
(狡猾的e:村庄:在合作社)

带有
@计数器的版本将起作用,但不是出于您想要的原因:
:while
将只“跳过”当前的
x
绑定并移动到下一个绑定,这意味着
计数器需要为每个
x
测试一次,即使它不再更改。对于较小的
贴图宽度
,这很好,但是对于较大(或无限)宽度,这是一个严重的问题。@amalloy确实,
x
需要自己的
:while
!谢谢你发现了这个错误,我马上就修好。(编辑:完成;还修复了措辞。)有趣的是,SO的语法突出显示是否基于问号?似乎认为分号是comments@jozefg它使用了一些东西,但是是的,它使用了标签
;; some stub stuff to get the example to run
(ns example.core
  (:use clojure.math.combinatorics))

(def max-villages 5)
(def map-width 10)
(def map-height 10)
(defn crafty-e [x y z] (print z))

;; the example, note I use doseq rather than map to empasize the fact that the loop 
;; is being performed for its side effects not its return value.
(doseq [coord (take max-villages 
                (filter 
                 (fn [_] (< (rand)  0.02))
                 (cartesian-product (range map-width) (range map-height))))]
(crafty-e :village :at coord))