【问题标题】:Using break from loop in Racket在 Racket 中使用循环中断
【发布时间】:2016-07-31 15:38:19
【问题描述】:

我可以使用来自 While Loop Macro in DrRacket 的代码在 Racket 中使用“while”循环

(define-syntax-rule (while-loop condition body ...)   
  (let loop ()
    (when condition
      body ...
      (loop))))

但是,我想在无限循环中使用 break,如下所示:

(define (testfn)
  (define x 5)
  (while-loop #t          ; infinite while loop; 
    (println x)
    (set! x (sub1 x))
    (when (< x 0)
       (break))))         ; HOW TO BREAK HERE; 

如何在上面的无限循环中插入中断?感谢您的 cmets/answers。

【问题讨论】:

  • 问题中的代码使用了命令式风格,这不是我们在Scheme中编写循环的方式。

标签: scheme racket


【解决方案1】:

你没有。 Racket 属于 Scheme 系列,因此所有循环实际上都是通过递归完成的。

您通过不递归来跳出循环。任何其他值都将成为表单的结果。

(define (helper x) 
  (displayln x) 
  (if (< x 0)
      'return-value
      (helper (sub1 x))) 
(helper 5)

有一些宏可以使语法更简单。使用命名let 是一个:

(let helper ((x 5))
  (displayln x) 
  (if (< x 0)
      'return-value
      (helper (sub1 x)))

查看您的 while-loop 只是一个使用名为 let 的宏的宏,该宏变成了一个递归过程。

如果您而不是 #t 编写一个最终变为 false 的表达式,它将停止。喜欢:

(while-loop (<= 0 x)
  ...)

请注意,使用set! 在循环中更新变量不被认为是好的做法。如果您正在学习 Racket,请尽量不要使用 set! 或您的新循环结构。尝试使用命名为letletrec

【讨论】:

    【解决方案2】:

    正如链接问题的已接受答案中所述,推荐 - 完全不推荐!以这种方式循环。使用标准 Scheme 时,避免使用命令式循环并更喜欢递归(使用帮助程序或命名的 let),或者在 Racket 中使用 iterations and comprehensions

    另外,break 不是标准的 Scheme 构造。考虑使用不需要显式中断并避免命令式风格的更惯用的 Racket 重写逻辑:

    (define (testfn n)
      (for [(x (in-range n -1 -1))]
        (println x)))
    
    (testfn 5)
    => 5
       4
       3
       2
       1
       0
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-06-10
      • 1970-01-01
      • 2016-12-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多