我正在尝试创建一个循环,询问命令,执行命令,然后再循环。只有输入的命令是“退出”才会退出。我尝试了几个不同的东西,但是当我运行它们时,它们工作一次(read-line)读取#然后无限地执行此操作而不等待输入。我最初的尝试看起来像这样:
(define (inputLoop)
(define command "init")
(do()((equal? command "exit") (display "exited successfully..."))
(display "What would you like to do?(start,stop,exit)")
(set! command (read-line))
(cond [(equal? command "start") (start)]
[(equal? command "stop") (stop)]
[else (void)])))
我的下一次尝试是类似的,但是如果命令不是“退出”,它只是递归地调用名为inputLoop的函数而不是使用do循环。
以下是输出示例:
What would you like to do?(start,stop,exit)start
What would you like to do?(start,stop,exit)
What would you like to do?(start,stop,exit)
...<thousands-of-lines-here>
What would you like to do?(start,stop,exit)
What would you like to do?(start,stop,exit)
What would you like to do?(start,stop,exit)exit
exited successfully...
答案 0 :(得分:6)
这是您所描述的简单版本:
(define (input-loop)
(display "What would you like to do? (start,stop,exit)")
(define command (read-line))
(cond [(string=? command "start") (start) (input-loop)]
[(string=? command "stop") (stop) (input-loop)]
[(string=? command "exit") (displayln "exited successfully...")]
[else (displayln "unknown command") (input-loop)]))
你也可以在循环中有一个转义延续和中断;这与经典while True: [...] break
方法最接近:
(define (input-loop)
(let/ec break
(let loop ()
(display "What would you like to do? (start,stop,exit)")
(define command (read-line))
(cond [(string=? command "start") (start)]
[(string=? command "stop") (stop) ]
[(string=? command "exit") (break)]
[else (displayln "unknown command")])
(loop)))
(displayln "exited successfully..."))
请注意,在第二种情况下,您可以方便地将结束逻辑(display "exited successfully"
)放在过程的末尾,而在第一种情况下,您需要将其放入循环中,否则代码可能是执行了好几次。
在命令行(OS X)上执行示例:
pu@pumbair: ~/Projects/L-Racket racket input-loop.rkt
What would you like to do? (start,stop,exit)a
unknown command
What would you like to do? (start,stop,exit)starr
unknown command
What would you like to do? (start,stop,exit)start
start!
What would you like to do? (start,stop,exit)stop
stop!
What would you like to do? (start,stop,exit)exit
exited successfully...
使用此(模拟)版本:
#lang racket
(define (start) (displayln "start!"))
(define (stop) (displayln "stop!"))
(define (input-loop)
(let/ec break
(let loop ()
(display "What would you like to do? (start,stop,exit)")
(define command (read-line))
(cond [(string=? command "start") (start)]
[(string=? command "stop") (stop) ]
[(string=? command "exit") (break)]
[else (displayln "unknown command")])
(loop)))
(displayln "exited successfully..."))
(input-loop)
答案 1 :(得分:2)
在关注@uselpa关于检查我的start
和stop
方法的建议后,我得出的结论是我的问题出在我的start
方法中。它使用racket documentation中记录的(place id body ...+)
表单创建了几个并行运行的位置。文档说明,
bodys仅在id上加上封闭模块的顶层绑定
由于我的代码在顶层调用了循环,因此每个创建的位置在创建时执行循环。我的解决方案是使用记录为here的(dynamic-place module-path start-name)
表单。我只需将我的代码移动到外部文件。使用此方法无法从地址代码的调用代码访问顶级绑定。
进行这些更改后,我能够成功运行@uselpa在其答案中提供的两种循环技术,而不会出现任何无限循环或错误。