跳至内容

Scheme 编程/过程

来自维基教科书,开放的书籍,为开放的世界
Scheme 编程
 ← 条件语句 过程 循环 → 

到目前为止,我们已经使用了许多内置的 Scheme 过程(例如+, *,等等),但我们还没有看到如何定义我们自己的。过程是使用lambda形式创建的。这里有一个简单的例子

> (lambda (x) (* x x))
#<procedure>

评估 lambda 形式会返回一个过程对象,我们可以像对待任何其他值一样对待它。但是,与我们一直在使用的内置过程不同,这个过程缺少一些重要的东西——一个名字。因此,用 lambda 构造的过程被称为“匿名”;如果我们想要应用它们,我们必须将 lambda 表达式写成应用的运算符

> ((lambda (x) (* x x)) 4)
16

这是如何工作的?正如我们在前面章节中所看到的,我们通过首先评估运算符(这里它是 (lambda (x) (* x x)))和操作数来评估过程对某些参数的应用。我们的 lambda 表达式评估为一个(匿名)过程,它接受一个参数,x,它返回的值是x的平方。应用于值 4,这个过程返回 16。

命名过程

[编辑 | 编辑源代码]

只使用匿名过程编写程序是不切实际的——尽管并非不可能。即使是相对简单的程序,如果我们必须为每个运算符编写 lambda 表达式,而不是使用方便的名称,也会变得难以忍受地复杂。由于过程是值,我们可以使用define为它们命名,就像我们对任何其他值一样

> (define square (lambda (x) (* x x)))
> (square (square 2))
16

在这里,我们将 square 定义为表示过程 (lambda (x) (* x x))。一旦完成,我们就可以使用square作为我们喜欢的任何地方的过程。Scheme 不区分内置过程和新定义的过程,因此过程定义是 Scheme 程序员扩展语言的关键方式。

每次我们想写一个过程时,都要写 (define <name> (lambda (<arg> ...) ...)) 有点笨拙,所以 Scheme 提供了一个简写形式。我们也可以写下我们对square的定义如下

(define (square x)
  (* x x))

这个简写形式的一般形式是

(define (<name> <arg> ...) <body>)

这个定义与具有显式lambda表达式的定义相同,但它打字更快一些。您将在 Scheme 代码中不断看到这种定义形式。

可变数量的参数

[编辑 | 编辑源代码]

您还可以创建具有可变数量参数的过程

(define (sum . args)
  (apply + args))

这将创建过程 sum,它的工作原理与本机 + 过程完全相同。

这与以下代码相同

(define sum (lambda args
              (apply + args)))

请注意,args 参数周围没有括号,因此所有参数都将被放入名为 args 的一个列表中。

使用 lambda,如果您想有一个固定的参数,而其他参数是可选的,您可以使用不完整的列表

(define sum (lambda (first . rest)
              (/ first (apply + rest))))

有了它,您可以创建具有可选参数的过程

(define (rational first . rest)
  (let ((second (if (null? rest) 1 (car rest))))
    (/ first second)))

这将创建一个过程,当没有提供第二个参数时评估 (/ first 1),或者评估 (/ first second)

华夏公益教科书