Scheme 中的命名让

Named let in Scheme

我正在尝试使用命名 let 在 Scheme 中编写一个循环。我希望能够根据各种标准尽早结束迭代,而不是总是在最后循环。实际上,我想要 whilebreakcontinue。出于充分的原因,我不得不使用 guile 1.8,而 guile 1.8 没有实现 R6RS while 构造。我的问题是,使用命名 let 进行递归是否必须是尾递归,为什么不能在结束之前重新启动循环? [这需要代码示例吗?]当我尝试在多个 IO 操作点使用提前退出进行递归时,我总是读取过去的 EOF 并得到不可预测的数据损坏。

(let name ((iter iter-expr) (arg1 expr1) (arg2 expr2))
  (cond
    (continue-predicate (name (next iter) arg1 arg2)))
    (break-predicate break-expression-value)
    (else (name (next iter) next-arg1-expression next-ar2-expression))))

continue 只是使用大多数相同的参数再次调用,除了迭代的部分将更改为下一个内容之外,其余参数不变。

休息是基本情况。

那么什么是while?它是一个带有中断谓词和默认情况的命名 let

Scheme 并没有真正的 while 结构。如果您阅读该报告,您会发现它只是一个语法糖(宏),可以变成类似于命名 let 的东西。

如果你想在没有完成所有之前的计算的情况下退出它,你需要它是尾递归的。您还可以使用 call/cc 提供退出延续,这基本上是让 Scheme 在幕后为您完成。通常 call/cc 对初学者来说太过遥远,掌握它需要一些时间,所以让你的程序尾递归比做这样的事情更容易理解:

(define (cars lists-of-pair)
  (call/cc (lambda (exit)
    (fold (lambda (e a)
            (if (pair? e)
                (cons (car e) a)
                (exit '()))) ; throw away continuations to make current result make it ()
          '()
          lists-of-pair)))

(cars '((1 2) (a b))) ; ==> (1 a)
(cars '((1 2) ()))    ; ==> ()