Scheme中的“While”循环跳过迭代

时间:2014-03-30 21:00:34

标签: scheme

我必须学习Scheme的基础知识来完成一个项目,但是我在构建等效的while循环时遇到了一些困难。例如,在下面的代码中,我想让用户输入一个字符。如果字符是x,我想要摆脱循环。如果是任何其他字符,将显示该字符,循环继续下一次迭代。

(define getUserChar (lambda ()
(define ch)
  (let loop ()
    (display "Enter character: ")
    (set! ch (read-char))
    (if (not (char=? ch #\x))
       (begin
       (display choice)
       (loop)
 )))))

这在技术上确实有效,但它会跳过迭代。例如:

Enter character: a
Enter character:
Enter character: s

在第二次迭代期间,我无法输入字符。我似乎无法确定问题所在。非常感谢任何帮助。

2 个答案:

答案 0 :(得分:3)

问题在于您实际上正在阅读两个字符。你键入的那个,加上换行符。我试图尽可能地保留原始解决方案,这就是我想出来的:

(define getUserChar
  (lambda ()
    (define ch #\0)
    (let loop ()
      (display "Enter character: ")
      (set! ch (string-ref (read-line) 0))
      (if (not (char=? ch #\x))
          (begin
            (display ch)
            (newline)
            (loop))))))

恕我直言,一个更惯用的解决方案并不需要进行变异操作,我更喜欢这个:

(define (getUserChar)
  (let loop ((ch #\0))
    (unless (char=? ch #\x)
      (display "Enter character: ")
      (let ((ch (string-ref (read-line) 0)))
        (display ch)
        (newline)
        (loop ch)))))

答案 1 :(得分:2)

这与你在循环的第一次迭代中输入两个字符的事实有关,即"a\n""a~n"),这使得第二次迭代只需要{{1你和#\NewLine一起作为角色输入了。

如果你想在get-line(R6RS)或#\a(R7RS)的时候取一整行,或者看看buffer-mode(R6RS)并在开始之前啜饮这些字符新的迭代继续使用字符。