相当于SRFI 42:在Racket的理解中

时间:2013-05-15 21:16:10

标签: scheme racket list-comprehension

SRFI 42中的热切理解可以有一个:while子句在某些条件成立时运行生成器,例如:(list-ec (:while (:range i 10) (< (* i i) 50)) i)返回列表(0 1 2 3 4 5 6 7)(和停止迭代7,与if不同,例如在(list-ec (:range i 10) (if (< (* i i) 50)) i)中,它会继续运行,但不再生成值。)

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

2 个答案:

答案 0 :(得分:7)

您可以使用#:break循环中的for子句执行类似的操作。例如,我认为这与您的示例相同:

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

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

答案 1 :(得分:3)

我在文档中错过了它:答案是使用stop-before function。你可以翻译像:

(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默认会生成嵌套循环。此外,正如Asumu Takikawa所指出的那样,Racket在其理解中有一个#:break条款,但其工作方式不同:它不限制单个发生器,而是退出整个循环。