147*_*7pm 4 scheme elisp common-lisp racket
据我所知 - 如果错误我会在这里纠正 - 良好的Scheme实践是做任何需要循环的事情,重复递归,而且溢出不会成为问题,因为尾部递归是内置的.Lisp的,但是,没有保护免受溢出,因此,所有的循环迭代宏(loop,while,等).因此在现实世界的Lisp中,你通常不使用递归,而Scheme只需要它.
如果我的假设是正确的,有没有办法用Lisp"纯粹"而不是冒险溢出?或者这对游戏来说太过游泳以在Lisp中使用递归?我从The Little Schemer回忆起他们如何通过递归给你一个彻底的锻炼.还有一个名为The Little Lisper的早期版本.它是否在Lisp中为您提供相同的递归训练?然后Land of Lisp让我对循环或递归是否是"最佳实践"感到困惑.
我要做的是决定是否在Emacs组织模式中使用Racket,或者只为初学者使用内置的Elisp.我希望学生保持尽可能纯粹的功能,例如,我不想解释递归的新的和困难的话题,然后说"哦,但我们不会使用它......"
据我所知 - 如果错误我会在这里纠正 - 良好的Scheme实践是做任何需要循环的事情,重复递归,而且溢出不会成为问题,因为尾部递归是内置的.
据我所知,这是正确的.
但是,Lisp没有溢出保护[...]
不完全是.大多数自我相应的Common Lisp实现提供尾调用合并(有一些限制,请参阅https://0branch.com/notes/tco-cl.html).不同之处在于语言规范没有要求.这样可以在实现各种Common Lisp功能时为编译器编写者提供更多自由.Emacs Lisp没有TCO,除了以recur或tco(自递归)等库的形式.
...因此,所有循环迭代宏(循环,而等).因此在现实世界的Lisp中,你通常不使用递归,而Scheme只需要它.
差异主要是文化.取一个REPL(Read-Eval-Print- Loop).我认为将交互视为循环而不是无限尾递归函数更有意义.不知何故,在纯函数式语言中似乎有些不情愿甚至将循环视为原始控制结构,而迭代过程被认为更优雅.为什么不两个?
如果我的假设是正确的,有没有办法用Lisp"纯粹"而不是冒险溢出?或者这对游戏来说太过游泳以在Lisp中使用递归?
你肯定可以在Lisp中使用递归,只要你不滥用它,小程序就不应该这样.例如,考虑map在OCaml中不是尾递归,但人们仍然经常使用它.如果您使用SBCL,手册中有一节说明如何强制执行尾部呼叫消除.
我要做的是决定是否在Emacs组织模式中使用Racket,或者只为初学者使用内置的Elisp.我希望学生保持尽可能纯粹的功能,例如,我不想解释递归的新的和困难的话题,然后说"哦,但我们不会使用它......"
如果您想教授函数式编程,请使用功能更强大的语言.换句话说,在Racket和Emacs Lisp之间,我会说Racket更适合学生.使用Racket教授功能编程的材料还有很多,还有Typed Racket.
典型的Lisp方言和各种Scheme方言之间存在很多差异:
方案
口齿不清
部分内容适用于Lisp方言,如Emacs Lisp,Common Lisp或ISLisp.
实现通常对堆栈大小有严格的限制,这使得非TCO递归函数成为问题.通常,可以预先设置较大的堆栈大小或在运行时扩展堆栈大小.
尾调用优化与动态范围构造(如特殊变量或类似变量)有一些不兼容性.
有关Common Lisp中的TCO支持,请参阅:Common Lisp实现中的尾调用优化
样式