Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/clojure/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Clojure 在一个或多个嵌套循环中从函数返回?_Clojure - Fatal编程技术网

Clojure 在一个或多个嵌套循环中从函数返回?

Clojure 在一个或多个嵌套循环中从函数返回?,clojure,Clojure,在一个或多个嵌套循环中,有没有方法可以立即从函数返回 下面是一些示例代码,用于说明问题: ; Grid data structure ; ------------------- (defstruct grid :width :height) (defn create-grid [w h initial-value] (struct-map grid :width w :height h :data (ref (vec (repeat (* w h) initi

在一个或多个嵌套循环中,有没有方法可以立即从函数返回

下面是一些示例代码,用于说明问题:

; Grid data structure
; -------------------
(defstruct grid :width :height)

(defn create-grid [w h initial-value]
  (struct-map grid
    :width  w
    :height h
    :data   (ref (vec (repeat (* w h) initial-value)))))

(defn create-grid-with-data [w h gdata]
  (struct-map grid
    :width w
    :height h
    :data (ref gdata)))

(defn get-grid [g x y]
  (let [gdata (g :data)
        idx   (+ x (* (g :width) y)) ]
    (gdata idx)))

(defn set-grid [g x y value]
  (let [data  (deref (g :data))
        idx   (+ x (* (g :width) y)) ]
    (dosync (alter (g :data) (fn [_] (assoc data idx value))))))

(defn get-grid-rows [g]
  (partition (g :width) (deref (g :data))))



; Beginning of test app
; ---------------------

; The Tetris playing field  
(def current-field (create-grid 20 10 0))


; A tetris block (the L-Shape)
(def current-block {
  :grid (struct-map grid :width 3 :height 3 :data [ 0 1 0
                                                    0 1 0
                                                    0 1 1 ])

  ; upper-left corner of the block position in the playing field
  :x (ref 0) 
  :y (ref 0)
} )


; check-position-valid checks if the current position
; of a block is a valid position in a playing field
(defn check-position-valid [field block]
  (dotimes [ x ((block :grid) :width) ]
    (dotimes [ y ((block :grid) :height) ]
      (if
        (let [ g           (block :grid)
               block-value (get-grid g x y)
               field-x     (+ x (deref (block :x)))
               field-y     (+ y (deref (block :y))) ]
          (if (not (zero? block-value))
            (if-not
              (and (>= field-x 0)
                   (< field-x (field :width))
                   (< field-y (field :height))
                   (zero? (get-grid field field-x field-y)))
              false ; invalid position, function should now return false
              true ; ok, continue loop
              )))
        true
        false))))

(println (check-position-valid current-field current-block))
;网格数据结构
; -------------------
(defstruct栅格:宽度:高度)
(定义创建网格[w h初始值]
(结构映射网格)
:宽度w
:高度h
:数据(参考(vec(重复(*w h)初始值‘‘‘)’)
(定义使用数据创建网格[w h gdata]
(结构映射网格)
:宽度w
:高度h
:数据(参考gdata)))
(定义获取栅格[g x y]
(let[gdata(g:数据)
idx(+x(*(g:宽度)y))]
(gdataidx)))
(定义设置网格[g x y值]
(let[数据(deref(g:数据))
idx(+x(*(g:宽度)y))]
(dosync(alter(g:data)(fn[0;](assoc data idx value ')))
(defn获取网格行[g]
(分区(g:宽度)(deref(g:数据)))
; 开始测试应用程序
; ---------------------
; 俄罗斯方块游戏场
(def当前字段(创建网格20 10 0))
; 俄罗斯方块(L形)
(def当前块{
:网格(结构贴图网格:宽度3:高度3:数据[0 1 0
0 1 0
0 1 1 ])
;运动场中拦网位置的左上角
:x(参考文献0)
:y(参考文献0)
} )
; check position valid检查当前位置是否有效
; 一个区块的位置是运动场中的一个有效位置
(defn检查位置有效[字段块]
(dotimes[x((块:网格):宽度)]
(点时间[y((块:网格):高度)]
(如果
(let[g(块:网格)
块值(获取栅格g x y)
字段-x(+x(数据块:x)))
field-y(+y(deref(block:y)))]
(如果(不是(零块值))
(如否)
(和(>=字段x 0)
(
也许我对这个问题的态度过于急迫

更新
好的,我找到了一个解决方案:

; check-position-valid checks if the current position
; of a block is a valid position in a playing field
(defn check-position-valid [field block]
  (let [stop-condition (ref false)]
    (loop [ x 0 ]
      (when (and (not (deref stop-condition))
                 (< x ((block :grid) :width)))
        (println "x" x)
        (loop [ y 0 ]
          (when (and (not (deref stop-condition))
                     (< y ((block :grid) :height)))
            (println "y" y)
            (let [ g           (block :grid)
                   block-value (get-grid g x y)
                   field-x     (+ x (deref (block :x)))
                   field-y     (+ y (deref (block :y))) ]
              (if (not (zero? block-value))
                (if-not
                  (and (>= field-x 0)
                       (< field-x (field :width))
                       (< field-y (field :height))
                       (zero? (get-grid field field-x field-y)))
                  (do
                    (println "stop is true")
                    (dosync (alter stop-condition (fn [_] true)))))))
            (recur (inc y))))
        (recur (inc x))))
    (not (deref stop-condition))))

(println (check-position-valid current-field current-block))
;check position valid检查当前位置是否有效
; 一个区块的位置是运动场中的一个有效位置
(defn检查位置有效[字段块]
(让[停止条件(参考错误)]
(循环[x0]
(何时(和(非(解除停止条件))
(=字段x 0)
(
它使用可变引用作为停止标志,打破了编程的功能风格。但我很高兴有一个解决办法。请随意分享更好的方式

更新

对于那些感兴趣的人,我已经完成了游戏的第一个版本。可以尝试一下:)

在循环递归结构中,您需要进行某种检查,以确定是否需要继续循环,如果需要,则进行循环,如果不需要,则返回一个值。在while循环中,您只需使谓词等于false。Clojure中没有中断和继续,因为它在Clojure中没有意义


我认为您正在寻找
循环
,而不是
dotimes

我认为您可以用一个惯用的高阶函数替换
dotimes
嵌套循环,该函数遍历数据集合并返回布尔值。例如,我认为这可能会有所帮助。

用loop/recur替换dotimes是正确的。现在,要去掉可变停止标志:

  • 添加第二个变量来表示循环的停止标志,如

    (loop [x 0 stop false] ...
    
  • 执行if/then,查看循环中的第一个操作stop标志是否为true

    (if stop (println "I'm all done) (...
    
  • 在有if not测试的嵌套代码的深处,让两个分支调用recur,并将相应的值设置为false。意译:

    (if (stop-condition-is-true) (recur y true) (recur (inc y) false))
    
  • 未经测试:

    (defn position-valid? [field block]
      (let [g (block :grid)]
        (every? true? (for [x (range 0 (inc (g :width)))
                            y (range 0 (inc (g :height)))
                            :let [block-value (get-grid g x y)
                                  field-x     (+ x @(block :x))
                                  field-y     (+ y @(block :y))]]
                        (and (not (zero? block-value))
                             (>= field-x 0)
                             (< field-x (field :width))
                             (< field-y (field :height))
                             (zero? (get-grid field field-x field-y)))))))
    
    (定义位置有效?[字段块]
    (让[g(块:网格)]
    (每?真?(适用于[x(范围0)(包括(g:宽度)))
    y(范围0(包括(g:高度)))
    :let[块值(获取栅格g x y)
    字段-x(+x@(块:x))
    字段-y(+y@(块:y))]]
    (和(非(零块值))
    (>=字段x 0)
    (

    for
    是惰性的,所以
    每一个?
    只会一直运行到它达到第一个非真值。

    因为在OP的另一个问题中,我为播放网格提出了一种不同的数据结构——即向量向量向量——我很想展示如何用这种表示来解决这个问题。对于这个问题,我认为使用
    0
    和<
    (defn check-position-valid [field-grid block]
      (let [grid-rect (subgrid field-grid
                               @(block :x)
                               (-> block :grid :width)
                               @(block :y)
                               (-> block :grid :height))
            block-rect (-> block :grid :data)]
        (and grid-rect
             (not-any? pos?
                       (mapcat #(map (comp dec +) %1 %2)
                               grid-rect
                               block-rect)))))
    
    (defn create-grid
      ([w h] (create-grid w h 0))
      ([w h initial-value]
         (let [data (vec (map vec (repeat h (repeat w initial-value))))]
           data)))
    
    (defn print-grid [g]
      (doseq [row g]
        (apply println row)))
    
    (defn subgrid
      "x & y are top left coords, x+ & y+ are spans"
      [g x x+ y y+]
      (if (and (<= (+ x x+) (count g))
               (<= (+ y y+) (count (first g))))
        (vec
         (map #(subvec % x (+ x x+))
              (subvec g y (+ y y+))))))
    
    (def current-block
         {:grid [[0 1 0]
                 [0 1 0]
                 [0 1 1]])
          :x (ref 0) 
          :y (ref 0)})
    
    (defn get-grid [g x y]
      (get-in g [y x]))
    
    (defn set-grid [g x y v]
      (assoc-in g [y x] v))
    
    (defn swap-grid [g x y f & args]
      (apply update-in g [y x] f args))
    
    (defn get-grid-row [g y]
      (get g y))
    
    (defn set-grid-row [g y v]
      (assoc g y (vec (repeat (count (g 0)) v))))
    
    (defn get-grid-col [g x]
      (vec (map #(% x) g)))
    
    (defn set-grid-col [g x v]
      (vec (map #(assoc-in % [x] v) g)))
    
    user> (print-grid (set-grid-row (set-grid-col (create-grid 6 10) 1 2) 0 3))
    3 3 3 3 3 3
    0 2 0 0 0 0
    0 2 0 0 0 0
    0 2 0 0 0 0
    0 2 0 0 0 0
    0 2 0 0 0 0
    0 2 0 0 0 0
    0 2 0 0 0 0
    0 2 0 0 0 0
    0 2 0 0 0 0
    nil