Scheme Script
注意!: Dr. Geo 的作者正在改用 squeak 從頭改寫 Dr. Geo II, 因此未來它的 scripting 語言可能改成 squeak, 而這個單元的講義也極可能不適用於 Dr. Geo II。 注意!
Dr. Geo 不只可以畫圖, 還可以拿來寫 scheme 程式。 別緊張, 不是完整的巨大程式, 只是簡單的程式片段, 像這樣:
(let* ( (a 3) (b 4) ) (sqrt (+ (* a a) (* b b))) )
[舊版講義的寫法如下, 也可以; 不過習慣上 define 用於函數與真正的常數; let* 稍微像傳統程式語言變數用法, 但它也不是設定變數, 因為 scheme 基本上是 functional language, 不鼓勵 「變數」 的思考方式。]
(define x 3) (define y 4) (sqrt (+ (* x x) (* y y)))
事先兩點提醒: Dr. Geo 的 scheme script 撰寫/除錯環境還不成熟, 如果你寫的 script 出錯, 會一直跳出錯誤訊息視窗, 關再多次也沒有用。 這時只能用橡皮擦把這個 script 擦掉, 重新再來一次。 因此建議把程式寫在自己的 editor 裡面 (例如 vim 或 emacs), 或是乾脆寫在 Dr. Geo 自己提供的文字頁面 ("create a new text"), 這樣寫錯的 script 擦掉以後還可以再剪貼回來。
- 選取 「數值」 工具底下的 「命令稿」, 然後在背景點一下, 產生一個空的 scheme script。
- 選取 「其他」 工具底下的 「更改物件屬性」, 然後在剛才產生的空白 scheme scrip 上面點一下, 於是跳出一個對話框。
- 把上面的程式剪貼進去, 並按確定。 畫布上應該出現 5。
可以猜得出來, 上面的程式用意在計算 sqrt(3*3+4*4) 。 不過它的運算式寫法卻有點奇怪, 採用 prefix notation -- 也就是把運算符號 (運算子 operator) 寫在前面; 數字 (運算元 operand) 寫在後面。
當然, 一個計算固定數字的 script 沒什麼好玩。 Dr. Geo 的 scheme script, 還可以接受參數, 算出來的值可以跟隨著圖上點線的位置大小改變。 暫時先不管 scheme 的語法, 我們先用 有向面積 (signed area) (或稱圍積 wedge) 為例, 學會如何製作 script。 兩個向量 (x1,y1) 與 (x2,y2) 張開一個平行四邊形, 它的有向面積是 x1*y2 - x2*y1。 這個簡單的公式可用於計算 (可凹可凸) 不規則多邊形的面積與重心, 或是力矩。
(let* ( (v1 (getCoordinates a1)) (v2 (getCoordinates a2)) ) (- (* (car v1) (cadr v2)) (* (cadr v1) (car v2))) )
- 畫兩個共用起點的向量, 分別叫它們 u 與 v 好了。
- 選取 「數值」 工具底下的 「命令稿」, 然後先在 u 點一下, 再在 v 點一下, 最後在背景點一下, 產生一個空的 scheme script。
- 一樣, 用 「更改物件屬性」 功能叫出編輯視窗, 把上面的程式貼進去。
- 拉動兩向量, 觀看這個數值的變化。 從 u 到 v 如果是逆時針旋轉, 算出來的就是正數; 如果是順時針旋轉, 算出來的就是負數; 如果兩向量共線 (同向或反向), 答案就接近 0。
scheme 語言初探
Scheme 是 lisp 類語言當中的一種方言 (dialect)。 Dr Geo 所採用的就是 scheme 方言的一個實作, 叫做 guile。 (就像 "文書處理軟體" 有很多類, 其中有一類是 「所見即所得的文書處理軟體」, OpenOffice.org 就是此類軟體的一個實作。) 如果您對這個語言有興趣, 請安裝 guile 套件, 並建一個文字檔叫做 ~/.guile 裡面放
(use-modules (ice-9 readline)) (activate-readline)
這樣才可以用 readline 提供的便利快速鍵。 在命令列底下打 guile 進入。 試幾個簡單的指令:
(define pi 3.1416) # 定義常數 pi # 查看 pi 的值 (set! pi 3) # 改變常數的值; 程式中建議避免使用 (set! pi (+ (* 3 3) (* 4 4))) # 遇到複雜算式, 由內往外算 (set! pi '(+ (* 3 3) (* 4 4))) # ' 阻止計算, 把後面當做資料 (car pi) # 取得 list 的頭 (cdr pi) # 取得 list 的身體 (扣除頭之外所有部分) (car (cdr pi)) # "身體的頭" 印出什麼? (cadr pi) # 等同上句效果
如前所述, lisp 語言是 functional language, 所以在程式中建議避免使用 set!, 而應常用 let* ("令" 的意思, 語法如上例)。 又, 從 car, cdr, cadr 的例子中, 可以看出為什麼這個語言叫做 lisp -- 專門用來 process list 的語言。 可以上網找一份 scheme tutorial 來試著照打看看, 例如勤益科大朱孝國老師的 Scheme Note, (網路上英文的 tutorial 超多的)
但其實也並不需要學那麼多。 對 Dr Geo 的愛好者而言, 畫圖可能遠比代數或寫程式有意思。 您只需要知道 let*, car, cdr, cadr 三四個指令, 再查詢一下 guile 文件 看看有沒有你心中想像的數學基本 函數 (例如 sqrt, sin, atan, ... 等等) 可以用, 就幾乎足夠。
剩下唯一的問題是: scheme 怎麼從 Dr. Geo 的圖當中取得資料? 一個 scheme script 如果接受畫面上的幾何物件當做參數, 第一個參數就叫做 a1, 第二個參數叫做 a2, ... 等等。 (彷彿系統已自動幫您 define 或 let* 過了) 這些幾何物件拿來不能直接用, 必須透過一些函數取得它的座標 (coordinates 或 abscissa), 長度 (length 或 norm), ... 等等。 這類與幾何物件有關的函數, 是 Dr. Geo 提供的, 在 guile 手冊裡面找不到。 但是 Dr. Geo 的手冊, 英文不完整且有點過時; 法文版 及其他歐洲語言版比較完整。 沒關係, 可以用 AltaVista 的 babelfish 服務, 翻譯成怪怪的英文版手冊, 湊合著看。 從 contents 可以找到 "methods of reference for script Dr. Geo", 這裡就是幾何函數列表。 所以現在回頭看有向面積的程式應該就沒有問題了。
Dr. Geo 的 scheme script 只能輸出一個數字, 無法輸出一個向量或其他更複雜的東西。 基於這些原因它並不適合用來寫太長, 太複雜的程式。
作業
- 請自行從頭製作 常態分佈
曲線如圖。 可以移動的地方包含:
- e1: x 軸上的單位點。 控制整個圖形的縮放。
- mu: 常態分佈的平均值。 左右移動時應帶著整個圖形移動。
- sigma: 常態分佈的一個標準差的位置。 移動時會改變曲線的高矮胖瘦, 但應永遠保持曲線底下面積為 1。
- s: 水平軸上任一點, 用來查詢常態分佈在任意一點的函數值。
- 本頁最新版網址: https://frdm.cyut.edu.tw/~ckhung/b/dg/script.php; 您所看到的版本: February 14 2012 10:32:25.
- 作者: 朝陽科技大學 資訊管理系 洪朝貴
- 寶貝你我的地球, 請 減少列印, 多用背面, 丟棄時做垃圾分類。
- 本文件以 Creative Commons Attribution-ShareAlike License 或以 Free Document License 方式公開授權大眾自由複製/修改/散佈。