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)。