我己經講過無限咁多次,我中三之後就無讀過電腦。
我是在 90s 時讀中學,當時中一至中三已有電腦課,但老老實實當時中一家中無電腦,上電腦課一舊雲一件事。另一件事是當時的電腦教育實在失敗非常。
我接受的基礎電腦課錯在甚麼?錯在沒有教任何實用軟件的應用技巧(如 Dos, ET3 ),卻將 Logo 當成是一種應用程式那樣去教。我好記得當時的老師說 Logo 係打機,輸入乜乜指令隻龜會動,係一個畫圖軟件。 ((我記得有同學問過為何不用 MS Paint ,但我已不記得老師怎樣答。))
上網一 search ,大把人覺得學 Logo 「無用」。
但是,為何當年要學寫 Logo ?我認為絕對不是當成畫圖軟件去用,甚至不是當成學一種 Programming Language ,而是學識如何去用電腦去解決問題。這些解決問題方法是無論用 Logo 也好、用 Cobol 也好、用 Python 又好、用 Brainfuck 都好,都仍然是 valid 的。
就讓我重新去學 Logo ,並用我認為正確的方法去教 Logo 。
事先聲明,我不是甚麼老師,也不是甚麼電腦科學家,故此我不是甚麼權威。香港教育出名多權威,故此你當我發噏瘋好了。 ((反正都是發噏瘋,不如講埋喇,香港教育權威出名在 grind any vestige of intellectual curiosity out of kids.))
為何想寫這些東西呢?除了我自己發現浪費了三年青春在很無謂的電腦教育,也因為讀了些 Brian Harvey 的書 ((Brian Harvey 寫了幾本書,都是 Intro CS 書,一本用 Scheme 另外三本用 Logo 。而 Logo 和 Scheme 都是 Lisp 的 dialect 。)) ,方發現為何當初 Logo 被選為教小孩電腦科學的語言。而香港的電腦教育完全達不到那個目標。
Logo 並不只是 Turtle ,還有些 List Processing 的功能在內。就算只當 Logo 等於 Turtle ,其實也可以玩到很多的東西。
學習的第一步是,怎樣裝一個 Logo 。
我記得以前用的 Logo 是 DOS 的,有 CGA 十六色,非常高科技。上網找找才知是叫做 HKULOGO ,不知道是不是由 HKU 編寫。我想找回那個 Logo ,在 DOSBOX 運行,可惜在 Google 找不到。
其實用網上的 Logo interpreter 已 OK 。當然,你也可以用 UCBLogo 。
第一課,最簡單,只用幾個基本指令( primitives ): FORWARD (FD), CLEARSCREEN (CS), PENUP(PU)/PENDOWN(PD), REPEAT, TO/END 。

Try yourself:

forward 40

就是將龜行前四十步。

clearcreen

就是將畫面清除。

clearscreen
pendown
forward 20
penup
forward 5
pendown
forward 20
penup
forward 5

pendown 就是叫隻龜放低支筆,再 forward 20 ,代表畫 20 步有色的線。 forward 20 之後是 penup ,代表筆己拿起,龜之後 forward 5 ,就算行了 5 步,但沒有填色。以上的一群指令,可以劃出一條虛線。
Big idea #1 是 pattern ((有沒有比「模式」更好的中文翻譯)) generalization 。從以上的一群畫虛線的指令,可以見到一個重覆了兩次的 pattern 。

pendown
forward 20
penup
forward 5

我們可以用 repeat 指令 ((非常深刻的記得那個電腦教師說 repeat 就是 recursion ,錯得很離譜。)) ,叫龜重覆同一套 pattern 。我們只需要用方括號把要重覆的 pattern 括住。 ((Block)) 例如我要龜重覆這個 pattern 兩次,就是:

clearscreen
repeat 2 [
pendown
forward 20
penup
forward 5
]

這個結果和之前一樣。當然,你也可叫龜重覆多於 2 次,例如:

clearscreen
repeat 7 [
pendown
forward 20
penup
forward 5
]

但是,我們想畫虛線時,只會想如:我想晝一條虛線。我們並不想像龜的(重覆兩次,起筆前行....)那樣運作。龜的運作方法,是龜行動的執行細節。舉個例,我們要解決肚餓的問題,具體的執行細節是 ((假設你有足夠金錢和時間)) :找出想吃或能吃的食物、獲食物、處理食物、將食物放進口裡、咀嚼、吞服、重覆 [將食物放進口裡、咀嚼、吞服] 直至食飽... 但是,當我們要解決肚餓的問題,我們想到的並不是具體的執行細節,而是一個抽象的概念,例如廣東話叫「食飯」、「食野」、「醫肚」;書面話叫「進餐」之類。我們會用抽象的概念,隱去具體的執行細節。 Big idea #2 是 abstraction ,就是用語意名稱來隱去執行細節。
例如畫虛線,我想用 dash 這個指令去叫龜虛線,而不是上面的那一群指令。一群的指令,可以稱為步驟 (Procedure) ,我們可以將一個 Procedure 命名,方法是用 to...end 的方法。

clearscreen
to dash
repeat 7 [
pendown
forward 20
penup
forward 5
]
end

執行以上的程序,你會見到龜沒有移動。這是因為 to...end 只是定義了名為 dash 這個 procedure ,並沒有執行。
在定義完之後要呼叫, procedure 才會執行。

clearscreen
to dash
repeat 7 [
pendown
forward 20
penup
forward 5
]
end
dash

但問題是我們並不想每次都叫龜畫長度為 7 的虛線。假設我想龜畫長度為 10 的虛線怎麼辨?
當然我們可以定義另一個叫 dash10 的 procedure 。

clearscreen
to dash10
repeat 10 [
pendown
forward 20
penup
forward 5
]
end
dash10

如是者,我們可以定義 dash0 至 dash999999.....99999 。但剛剛才講過,我們要找出 pattern 。在比較 dash 和 dash10 ,分別只是 repeat 的次數而已。我們想達到的目標是像 forward 那樣,在 forward 40 是行 40 步, forward 10 是行 10 步。同理,我們想 dash 7 是 7 步虛線, dash 10 是 10 步虛線。
Big idea #3 是 argument 。例如 forward 40 , 40 就是 forward 這個 procedure 的 argument 。 forward 的語法可以寫成是 forward n ,而 n 是 forward 的 argument ,而這個 argument 的作用是控制龜向前行的步數。
我們只需要修改 dash 的定義,就可以加入 argument 。

clearscreen
to dash :n
repeat :n [
pendown
forward 20
penup
forward 5
]
end
dash 10

當我們執行 dash 10 時,其實我們是將 10 這個數值送入 dash 的 :n 這個 argument 。 repeat :n 的 :n 也會變成 10 。同理,如我們執行 dash 189 時, :n 就是 189 , repeat :n 就變成 repeat 189 。
那麼,我們可以要 dash 2 又得, dash 100 都可以了。
一個 procedure 是可以有多於 1 個 argument ,例如我們想修改虛線的間距,可在 :n 之外再加 :l 的參數。

clearscreen
to dash :n :l
repeat :n [
pendown
forward :l
penup
forward 5
]
end
dash 10 5
dash 10 2
dash 10 1