Scheme 程式設計/Scheme 簡介
現在我們已經瞭解瞭如何執行 Scheme 直譯器,讓我們透過一些簡短的例子看看我們可以用它做什麼。我們不會深入研究這些程式。目前,我們的目的是讓讀者對 Scheme 有一個初步的瞭解。
Scheme 直譯器會評估使用者輸入的 Scheme 表示式。在我們的直譯器執行後,我們首先評估一個非常簡單的表示式。
> 4
4
當我們輸入 '4' 並按下回車鍵時,我們要求我們的 Scheme 直譯器評估表示式 '4'。不出所料,4 評估為 4。
接下來,我們嘗試一些基本的算術運算。
> (+ 3 6)
9
> (* 18 5) ; multiplication
90
> (- 4 7)
-3
這些例子說明了 Scheme 語法中的一些重要事項。首先,語法是完全括號化的;上面表示式中的括號是必需的,不能隨意新增括號,否則會改變表示式的含義。例如,以下會導致直譯器報錯
> ((+ 3 6))
;; Error: application of non-procedure 9
其次,我們看到 Scheme 使用字首表示法。在每個表示式中,運算子 (+, *, -) 位於運算元(數字)之前。這與我們通常使用的數學表示法(“中綴”)不同,在中綴表示法中,運算子位於運算元之間。例如,以下不是有效的 Scheme 表示式
> (8 * 5 - 3)
;; Error: application of non-procedure 5
然而,將其轉換為 Scheme 很容易
> (- (* 8 5) 3)
37
請注意,我們在這裡使用表示式 (* 8 5) 作為另一個表示式的運算元!這是有效的 Scheme,我們將在所有地方看到這樣的巢狀表示式。
Scheme 允許我們為值命名以便在其他表示式中使用
> (define x 20)
> x
20
> (define y (+ x 4))
> (* y 2)
48
定義 (define x 20) 使直譯器將 x 定義為 20 的值。當 x 出現在定義後的程式碼中時,它將被此值替換。然後,我們可以在 y 的定義中使用 x。
我們還可以定義過程。與內建運算子 +、- 等類似,過程接受一定數量的引數(也稱為引數),並計算一個值。
> (define (square x)
(* x x))
> (square 5)
25
在這裡,我們定義 square 表示一個接受一個引數 x 並返回 (* x x) 值的過程。此定義的形式與我們之前看到的略有不同;在這裡,定義的名稱出現在括號中,後面是過程引數的名稱。為了使用這個新定義的過程,我們評估 (square 5)。
這是一個更復雜的過程,它使用 海倫公式 計算邊長為 、 和 的三角形的面積
> (define (heron a b c)
(let ((s (/ (+ a b c) 2)))
(sqrt (* s (- s a) (- s b) (- s c)))))
> (heron 4 13 15)
24
在這個過程中,我們需要使用值 ,定義為
- ,
四次。如果我們要對 的每次出現都使用 (/ (+ a b c) 2) [1],那麼 heron 的定義將很繁瑣且難以閱讀。我們使用 let 形式來解決這個問題,它允許我們暫時將名稱 s 與此值相關聯。[2]
我們可以比較值,或者測試它們是否具有某些屬性。
> (= 4 (+ 3 1))
#t
> (< 9 7)
#f
> (positive? 5)
#t
> (even? 5)
#f
Scheme 返回給我們的 #t 和 #f 值是什麼?你可能已經猜到了,它們是分別代表“真”和“假”的布林值。
像 positive? 這樣的謂詞是接受一個引數並返回布林值的過程。在 Scheme 中,通常會給謂詞取以 '?' 結尾的名稱;因此,我們有 even?、negative? 以及許多其他謂詞。
過程可以是 遞迴 的。以下是一個經典的例子。
> (define (factorial n)
(if (= n 0)
1
(* n (factorial (- n 1)))))
> (factorial 5)
120
評估 (factorial 5) 會給出 的值,也就是 ,我們可以遞迴地表示為 。更一般地說,我們說 的階乘如果 為零則為 1,否則為 乘以 的階乘。這正是 factorial 的定義在 Scheme 語言中所述的內容
(define (factorial n)
(if (= n 0) ; is the argument 0?
1 ; then the answer is 1
(* n (factorial (- n 1))))) ; otherwise, it's n * (n - 1)!
遞迴是 Scheme(以及一般計算機科學)中一個重要的概念,我們將在後面的章節中更深入地討論。
factorial 定義中的另一個新事物是使用 if 表示式,它會先評估第一個引數,然後根據第一個引數的值為真還是假,分別評估第二個或第三個引數。如果第一個引數的值為真,那麼我們會得到 if 表示式的第二個引數;否則,我們會得到第三個引數。[3]
> (if #t 1 0)
1
> (if (> 2 3) 1 0)
0
| 練習 (解答) |
|---|
|