如何在 Clojure 中打破 for 循环?

How to break a for loop in Clojure?

我有以下功能:

(defn next-transformation
  [arr]
  (let [
        arr-len (count arr)
        i-range (range 0 arr-len)
        j-range (range 0 arr-len)
        indexes (for [i i-range
                      j j-range]
              (let [
                   xi (nth arr i)
                   xj (nth arr j)
                   ]
                (if (> xi xj)
                  [i j] 
                  nil
                  )
               )
            ) 
        non-nil-indexes (filter
                         (fn [elem]
                           (not (= elem nil))
                           )
                         indexes 
                        ) 
        ]
    (if (not (empty? non-nil-indexes))
       (first non-nil-indexes)
       nil
      )
    )
)

它 returns 元组数组的第一个元素 [i j] 描述数组 arr 的元素,其中 arr[i] > arr[j] 为真。

下面片段中的 for 循环遍历每一对 i 和 j:

indexes (for [i i-range
              j j-range]
      (let [
           xi (nth arr i)
           xj (nth arr j)
           ]
        (if (> xi xj)
          [i j] ;; I want the loop to stop here
          nil
          )
       )
    ) 

我如何修改这个 for 循环,以便它在找到第一个相关元组后停止(即循环应该在标有 ;; I want the loop to stop here 注释的地方停止)?

这是 Java 中的等效代码:

private Integer[] next-transformation(final Integer[] arr) {
  for (int i=0; i < arr.length; i++) {
     for (int j=0; j < arr.length; j++) {
       if (arr[i] > arr[j]) {
         return new Integer[] {i, j};
       }
     }
  }

}

更新 1:

根据@CharlesDuffy 的建议,我将 for 替换为 loop/recur:

(defn next-transformation
  [arr]
  (loop [i 0
         j 0]
    (let [
          arr-len (count arr)
          ]
      (if (and (< i arr-len)
               (< j arr-len))
        (let [
                xi (nth arr i)
                xj (nth arr j)
                j-plus-1 (+ j 1)
                i-plus-1 (+ i 1)
                new-i (if (< j-plus-1 arr-len)
                       i
                       (+ i 1))
                new-j (if (< j-plus-1 arr-len)
                       (+ j 1)
                       0)
              ]
          (if (> xi xj)
              ;; We found it
              [i j] 
              ;; We haven't found it, recur 
              (recur new-i new-j)
            )
          )
          nil ; We are at the end of the  loop
        ) ; if 
      )
    ) ; loop 
  ) ; defn

for 列表理解中,使用 :when 过滤感兴趣的元组,并使用 first 到 return 仅第一个:

(defn next-transformation [arr]
  (first (for [i (range (count arr))
               j (range (count arr))
               :when (> (nth arr i) (nth arr j))]
           [i j])))