0

SRFI 42中的急切推导可以有一个:while子句在某些条件成立的情况下运行生成器,例如:(list-ec (:while (:range i 10) (< (* i i) 50)) i)返回列表(0 1 2 3 4 5 6 7)(并在 7 处停止迭代,不像ifin(list-ec (:range i 10) (if (< (* i i) 50)) i)那样会继续运行但不会产生更多值)。

在 Racket 中,我通常更喜欢使用原生的forand for/list,但它们似乎没有内置这样的东西。:while在 Racket中模拟的最佳方法是for什么?

4

2 回答 2

7

您可以#:break在循环中使用该子句for来执行类似的操作。例如,这是我认为与您的示例等效的内容:

(for/list ([i (in-range 0 10)]
           #:break (> (* i i) 50))
     i)

#:break条件成立时,这将停止迭代。您还可以使用#:when过滤迭代而不是停止。有关更多选项,请参阅文档

于 2013-05-15T21:45:37.753 回答
3

我在文档中以某种方式错过了它:答案是使用stop-beforefunction。您可以翻译如下内容:

(list-ec (:while (:integers i) (< (* i i) 10))
         (:while (:integers j) (< (* (+ i 1) j) 10))
       (list i j))

(for*/list
     ([i (stop-before (in-naturals 0) (λ (i) (>= (* i i) 10)))]
      [j (stop-before (in-naturals 0) (λ (j) (>= (* (+ i 1) j) 10)))])
  (list i j))

请注意,我们需要星号版本,for*/list因为list-ec默认情况下会产生嵌套循环。此外,#:break正如 Asumu Takikawa 所指出的,Racket 在其理解中包含一个子句,但其工作方式不同:它不限制单个生成器,而是退出整个循环。

于 2013-05-16T04:01:21.193 回答