序章:如何編寫程序
1.序幕
本書使用的是編輯器DrRacket,使用的是其中的選擇語言——教學語言——程序設計初級,選擇之后重新點擊運行即可。
該編輯器的下半屏幕是交互區,上半屏幕是定義區,編輯文件以后,可以保存以后,點擊運行,從而在下方的交互區看到輸出結果。比如,在定義區輸入:
(+ 1 1)
你會看到底部交互區呈現的結果是:
2
這樣,你就可以輸入下面這幾個表達式,看看交互區會得到什么結果:
(+ 2 2)
(* 3 3)
(- 4 2)
(/ 6 2)
結果應該是4 9 2 3
,就好像你期待的一樣。下面,是不得不進行的術語定義時間。
術語
- 程序由表達式構成。你可能有看到一些數學上的表達式,但是,一個表達式可以是一個數字或者其他被括號
()
包圍的東西——成對的括號及其內容物會被DrRacket用陰影覆蓋。 - 當你點擊運行的時候,編輯器會對定義區的表達式求值,病將其返回值輸出到交互區的頂部,然后等待你的下一條命令;得到你的命令(輸入的表達式)后,其會對表達式求值,返回結果,再次進入等待狀態??聪旅孢@幾條交互區的實例:
> (+ 2 2)
4
> (sqr 3)
9
> (sin 0)
0
> (cos pi)
#i-1.0
- 最后一個表達式里面添加了前綴
#i
,表示這是一個不精確的數字(inexact number)。
介紹了足夠的術語后,下面繼續。我們可以發現,這里的DrRacket
可以加總兩個以上的數字,還可以嵌套!
> > (+ 2 (+ 2 3))
7
> (+ 2 3 2)
7
第一個是所謂的嵌套算數,正如在學校里面學到的。而第二個則是火箭算數,且它看起來是自然的,如果你總是將操作符和操作數用括號包圍起來的話。在教學語言——HtDP——BSL中,你可以任意使用嵌套表達式,其中表達式的左端是操作符,右端是操作數,嵌套層級則隨你使用:
> (+ 2 (+ (* 3 3) 4))
15
> (+ 2 (+ (* 3 (/ 12 4)) 4))
15
> (+ (* 5 5) (+ (* 3 (/ 12 4)) 4))
38
但是,要注意:括號必須是成對的,既不能多,也不能少。比如下面這個表達式,在作業中是沒有問題的:
> (+ (1) 2)
function call: expected a function after the open parenthesis, but found a number
結果會報錯……
P.S. 你可以將光標移動到操作符的附近,按下<kbd>F1</kbd>,然后你就可以獲取所需要的幫助文檔了。
如果你不知道一個操作符有什么用,就在交互區輸出示例,然后查看結果。這也是之后閱讀代碼所需要的技能。
2. 數字之外的內容
如果程序只能處理數字,會跟mathematics一樣無聊(雖然看這個的人可能已經在使用或者之后需要使用它)。但幸運的是,這里可以處理數字以外的東西,比如:文本、布爾值、圖片等等。
下面是文本處理的示例程序:
(string-append "hello" "world")
(string-append "hello" " " "world")
(string-append "hel" "lo world")
當你輸入病運行上述代碼的時候,下面的交互區會顯示:
"helloworld"
"hello world"
"hello world"
為了理解發生了什么,你需要知道:在BSL中,文本是用雙引號包圍起來的字符。當DrRacket
對字符串求值的時候,會返回字符本身。所以HelloWorld
在這里特別簡單,只需要輸入"Hello world!"
即可。
而string-append
本身則是操作符之一,作用是將多個字符串從左到右順序連接起來,只是連接了字面值,而沒有加入換行符之類的內容。如果想知道更多與字符串相關的操作符,可以按下<kbd>F1</kbd>,然后搜索Begin
,點擊Beginning Student
。
如果你已經做了上面所述的工作,你應該能看到這些內置(或者說預定義)的,與字符串相關的操作符了。然后,就可進行相關的操作,如下:
> (+ (string-length "Hello world!") 20)
32
然后,DrRacket會對表達式進行求值,打印結果。這意味著,你的輸入可以不只是數字,輸入和輸出的類型可以不同,比如下面展示的類型轉換函數:
> (number->string 42)
"42"
> (string->number "42")
42
恩……如果你希望能得到四二
之類的答案,可能要大失所望了——這并不是一個字符串操作符能做到的事情……
而這第二個操作符會使人產生疑惑:如果輸入的不是一個數字字符串,二是其他東西,會怎么樣呢:
> (string->number "Hello")
#false
得到了一個布爾值的錯誤。在DrRacket中,布爾值由兩個值表示:#true/#false
。自然,其也能夠支持邏輯運算符and
、or
和not
。雖然把數字轉換為布爾值不可行,但是可以將兩個以上的數字“轉換”為布爾值:
(> 10 9)
(< -1 0)
(= 42 42)
(= 3 4)
; 返回值
#true
#true
#true
#false
你可以開始嘗試下面這幾個表達式(>= 10 10)
、(<= 3 4)
和(string=? "design" "tkinter")
。雖然最后一個長得有點奇怪,但是要相信自己:你可以的~
在進入真正的編程之前,會展示一種額外的數據:圖片。如果需要將圖片插入交互區,你只需要將下面這張圖:
插入交互區,就可以看到DrRacket
返回圖片本身了。
P.S. 你可以使用插入菜單,并點擊插入圖片來完成這個壯舉。
這里,BSL可以理解圖片,如同理解數字和字符串一般。除此之外,該語言還支持一個包,。這些包可以像擴展你的詞典一般,為你的程序詞典添加新的內置函數。我們在教學中會使用這些包,并稱其為教學包。
現在,我們可以使用包2htdp/image
,其支持對圖片的計算:
輸入如圖所示的程序以后,你可以得到一個返回值:1176,因為這個圖的面積為28 X 42 像素。當然,你還可以使用一些函數來進行畫圖,如circle
函數和rectangle
函數:
(circle 10 "solid" "red")
(rectangle 30 20 "outline" "blue")
除此之外,DrRacket
還支持圖像之間的組合,如下:
(overlay (circle 5 "solid" "red")
(rectangle 20 20 "solid" "blue"))
將兩張圖片的構造函數換個順序,你會發現結果有所不同:
(overlay (rectangle 20 20 "solid" "blue")
(circle 5 "solid" "red"))
在這里,你可以將overlay
視作string-append
,其像后者一樣,操作數的先后會影響結果,與此同時,你還可以對其使用前面的求寬度操作符:
(image-width (square 10 "solid" "red"))
(image-width
(overlay (rectangle 20 20 "solid" "blue")
(circle 5 "solid" "red")))
; 結果
10
20
除了這些,你還應該知道另外兩個操作符:empty-scene
和place-image
。前者創建一個場景,屬于特殊的矩形;后者則將一張圖放置到這樣的場景中。
(place-image (circle 5 "solid" "green")
50 80
(empty-scene 100 100))
你看,結果如下:
其中,這幅場景的原點(0, 0)位于左上角,y值向下遞增;x值向左遞增。所以你看到的坐標(50, 80)是在那里。
現在總結一下這節的內容:
我們不再只是處理數字,而且可以處理字符串,布爾值以及圖片。計算現在依舊意味著:給表達式傳入特定的值,如字符串,數字,布爾值或者圖片。但是,你下次就可以讓這個火箭“飛起來”了。