如何使用 Scheme 在线解释器
- 在编辑器中编写或粘贴 Scheme 代码。重置示例会恢复初始程序,它会输出一个阶乘、前十个斐波那契数和一个平方和。
- 点击运行,或使用 Ctrl + Enter(Mac 上为 ⌘ + Enter)。
- 用
display、write和newline写出的文本会显示在输出面板中。程序运行结束后,最后一个表达式的值会以=> 值的形式输出,除非该值未指定。出错时会显示 BiwaScheme 自带的错误信息。 - 选择 5 秒、15 秒或 60 秒的时间限制。死循环会被自动终止,停止可以立即结束当前运行。
这个解释器只有约 0.3 MB,所以页面几乎立刻就能使用。复制和 main.scm 可以保存您的程序,全屏(Ctrl/⌘ + Shift + F,按 Esc 退出)会让编辑器占满整个窗口。
您的代码在浏览器内的 Web Worker 中运行,不会发送到任何服务器。编辑器会把您最近的程序自动保存在浏览器的本地存储中,本站的每个编译器各自独立保存。
关于 Scheme 和 BiwaScheme
Scheme 是 Lisp 的一个小型方言。程序由带括号的表达式构成,函数就是普通的值,递归是最常见的循环方式。它的核心非常精简,因此是讲解闭包、高阶函数和解释器时很受欢迎的教学语言。
本页运行的是 BiwaScheme 0.8.3,这是一个用 JavaScript 编写的 Scheme 解释器。它在风格上遵循 R6RS 和 R7RS 标准,涵盖了最常见的 Scheme 功能,但并不是这两个标准中任何一个的完整实现。
支持哪些功能
- 核心语法形式:
define、lambda、let、let*、letrec、if、cond、begin和set!。 - 列表与高阶函数:
cons、car、cdr、list、map、apply,以及'(1 2 3)这样的引用数据。 - 正确的尾调用,因此用具名
let或尾递归函数写成的循环,只占用固定大小的栈空间。
局限:
- 没有输入框。请把测试数据直接写在程序里。
- 不是完整的标准实现。MIT Scheme、Racket 或 Guile 等其他 Scheme 特有的过程可能缺失。
- 只会运行编辑器中的代码。没有可以加载的文件,也没有包管理器。
示例:普通递归与具名 let
;; 普通递归:每次调用都要等下一次调用返回。
(define (sum-list lst)
(if (null? lst)
0
(+ (car lst) (sum-list (cdr lst)))))
;; 具名 let:带累加器的尾递归循环。
(define (sum-to n)
(let loop ((i 1) (acc 0))
(if (> i n)
acc
(loop (+ i 1) (+ acc i)))))
(display (sum-list '(1 2 3 4))) (newline) ; 10
(sum-to 100000) ; => 5000050000
最后一个表达式不会被 display 输出,所以它的值显示为 => 5000050000。sum-list 会积累待完成的加法,而 sum-to 在尾位置调用 loop,行为就像 while 循环。
常见错误
- 忘记给列表加引用。
(1 2 3)会尝试把1当作函数来调用,从而报错。请写成'(1 2 3)或(list 1 2 3)。两者并不相同:'(a b)是由符号a和b组成的列表,而(list a b)会对变量求值。 define与let的区别。顶层的define会创建全局名称。let创建的局部名称只在它的主体内部有效。在普通的let内部,一个绑定不能引用另一个绑定,所以当后一个值依赖前一个值时,请使用let*。display与write的区别。display输出字符串时不带引号,write则保留引号,这在调试数据时很有帮助。- 相等性判断。比较数字用
=,比较符号用eq?,按内容比较列表或字符串则用equal?。
常见问题
这是 Scheme 编译器还是解释器?
是解释器。BiwaScheme 直接在浏览器中运行您的程序,没有单独的编译步骤。
支持哪个 Scheme 标准?
BiwaScheme 在风格上遵循 R6RS 和 R7RS,涵盖了最常见的功能。使用 define、lambda、let、cond、列表和递归的标准教科书代码都能按预期运行。依赖某个特定实现的库的代码,可能需要修改。
可以用它做 SICP 或课程练习吗?
可以,只要练习基于核心 Scheme。如果某道练习用到了未定义的过程,请在程序开头自己写一个简单版本。
为什么我的程序什么都没输出?
只有 display、write 和 newline 会产生输出,另外还有最后一个表达式的值所对应的 => 那一行。如果程序以 define 结尾,就不会显示任何值,因为它的结果是未指定的。
还能在线运行哪些其他语言?
想试另一种 Lisp,可以用Clojure在线编译器;想做逻辑编程,可以用Prolog在线编译器;也可以浏览所有在线编译器。
更新于
评论
登录后即可为此工具评分。
分享技巧、提出问题,或说说这个工具对您是否有用。
还没有评论,来分享您的使用体验吧。