使用 Chez Scheme

Chez Scheme 常常以交互的方式来支持程序开发和排除错误,它也可以使用非交互组件来创建 独立应用。本章描述了 Chez Scheme 一贯如何使用,更一般地讲,是如何充分利用系统。 2.1,2.2 和 2.3 节描述了如何交互地使用 Chez Scheme。2.4 节讨论了在 Chez Scheme 中如何使用库和 RNRS 顶级程序。2.5 节包含了支持写和运行编译的脚本和编译的 RNRS 顶级程序。 2.6 节描述了如何通过组织和编译应用来尽可能充分利用编译器,获得更高效的代码。2.7 节描述了如何定制启动 过程,例如,改变或排除命令行选项,预加载 Scheme 或外部代码,或将 Chez Scheme 作为 另一个程序的低级别程序来运行。2.8 节描述了如何用 Petite Chez Scheme 作为运行时来支持 Chez Scheme 构建的应用。最后,2.9 节包含了调用 Chez Scheme 时使用的命令行参数。

2.1 节 和 Chez Scheme 交互

一个最简单和高效的书写和测试 Scheme 程序的方法是组合使用文本编辑器像 viemacs 和在运行了 Chez Scheme 的 shell 窗口里交互地测试。如果 Chez Scheme 按默认选项安装,在 shell 提示符 中键入 scheme 命令来启动一个交互的 Scheme 会话。在 Petite Chez Scheme 中,petite 命令 做了同样的事情。在键入这个命令后,应该会看到简短的问候后跟只有一个尖括号的一行,像这样:

Chez Scheme Version 9.5.1
Copyright 1984-2017 Cisco Systems, Inc.  

>

你应该也看见了位于尖括号右侧的光标。这个尖括号是系统的 REPL 发出的,它代表了 “读(R)求值(E)打印(P)循环(L)”, 如此称谓是因为它会读,求值并打印表达式,然后循环回下一轮读,求值,打印,诸如此类。(在 Chez Scheme 里, REPL 也被称为 waiter)

为回应提示符,你可以键入任何 Scheme 表达式。如果这个表达式是符合语法规则的,REPL 会运行表达式并打印其值。 这里有一些例子:

> 3
3
> (+ 3 4)
7
> (cons 'a '(b c d))
(a b c d)

REPL 使用的 reader 比普通的 reader 更复杂。事实上,它是一个成熟的,像一个常规文本编辑器但一次只能编辑一个表达式 的“表达式编辑器”(简写为 “expeditor”)。一件你马上可能注意到的事是这个系统会自动缩进一个表达式的第二及后续的行。 举个例子,比如说我们想定义 fact,一个实现了阶乘函数的过程。如果我们键入 (define fact 后跟回车键,光标应该 位于 define 的第一个 e 下面,至此如果我们接着键入 (lambda (x) 我们应该看到:

> (define fact
    (lambda (x)

expeditor 也允许我们在表达式内四处移动(即使跨多行),编辑表达式来修正错误。接着键入:

> (define fact
    (lambda (x)
      (if (= n 0)
          0
          (* n (fact

我们也许注意到,过程的参数命名为 x,但已被我们引用为了 n。我们可以用箭头键移回第二行,用退格键删除这个惹麻烦的 x, 替换它为 n

> (define fact
    (lambda (n)
      (if (= n 0)
          0
          (* n (fact

我们这下可以用箭头键回到表达式的结尾,并完成定义。

> (define fact
    (lambda (n)
      (if (= n 0)
          0
          (* n (fact (- n 1))))))

现在我们有了一个圆括号平衡的完全形式,如果我们在刚在最后的圆括号之后的光标处敲下回车键,expeditor 将把它送给求值器。 我们得到另一个右尖括号提示符时,我们就知道它已被接受。

现在我们可以通过输入一些东西来测试我们的定义了,说 (fact 6) 来获得提示符的响应:

> (fact 6)
0

打印的值不是我们所希望的,因为是 6 而实际上是 720。问题显然出在基础情况的返回值是 0 而不是 1。幸运的是,我们并不需要 为了修正错误而重新键入这个定义。替代地,我们可以使用 expeditor 的历史机制取回早前的定义。上箭头键可以贯穿历史向后移动。 这种情况下,第一次按上箭头键会取回 (fact 6),第二次会取回 fact 的定义。

当我们向后移动历史时,表达式编辑器只给我们显示第一行,因此在两次向上箭头后,这是我们看见定义的全部:

> (define fact

我们可以通过键入 ^L (control L,也就是 control 和 L 键一起按)强制 expeditor 显示整个表达式:

> (define fact
    (lambda (n)
      (if (= n 0)
          0
          (* n (fact (- n 1))))))

现在我们可以移动至第四行并将 0 改成 1。

> (define fact
    (lambda (n)
      (if (= n 0)
          1
          (* n (fact (- n 1))))))

我们现在已经准备好输入这个正确的定义了。如果光标在第四行我们按下回车键,然而它只会在旧的第四行和第五行之间开一个新行。 这在其它状况下可能是有用的,但不是现在。当然,我们可以通过用箭头键移动到表达式的结尾来变通,但更简单的方式是键入 ^J ,这将强制表达式立即被输入而无论光标在何处。

results matching ""

    No results matching ""