λ 運算︰概念導引之《補充》※登堂嚐鮮

工匠祖師爺

鲁班锁

曲尺

古代傘

禮記‧檀弓下

季康子之母死,公輸若方小,斂,般請以機封,將從之,公肩假曰:『不可!夫魯有初,公室視豐碑,三家視桓楹。般,爾以人之母嘗巧,則豈不得以?其母以嘗巧者乎?則病者乎?噫!』弗果從。

魯班的姓名古籍上載有公輸班、公輸盤及公輸般等等,是春秋末年的著名工匠,被後世尊為中國工匠祖師爺。傳聞魯班出生於魯國之世家『公輸』大家族,所以後來多以『魯國之班』稱之,因此成為『魯班』。歷史流傳著許多魯班所設計的『工具』與建造之『法規』,尤其他對『建築』和『木工』等行業具有巨大貢獻。

《墨子‧天志上》中說:輪匠執其規矩,以度天下之方圓。

這個『』就是『畫圓』的『圓規』。而這個『』就是『畫方』的『曲尺』。傳說曲尺是魯班所發明的,後世稱之為『魯班尺』。《事林廣記‧引集》卷六中講『魯班尺法』:其尺也,以官尺一尺二寸為準,均分為八寸,其文曰、曰、曰、曰、曰、曰、曰、曰;乃主北斗中七星與主輔星。用尺之法從財字量起,雖一丈、十丈不論,但於丈尺之內量取吉寸用之;遇吉星則吉,遇凶星則凶。恆古及今,公私造作,大小方直,皆本乎是。作門尤宜仔細。又有以官尺一尺一寸而分作長短寸者,或改吉字為本字者,其餘並同。

傳聞又說『魯班之妻』也是位出色的工匠,因為疼惜魯班經常得在戶外『風雨烈日』下工作,發明了『』── 行動『』子 ── ,使他能有個『驅避之所』。

在《加百利之號角!!》一文中,我們談過『學習工具箱』的重要性。俗話說︰工欲善其事,必先利其器,在此介紹一個可以放進工具箱裡收集的 JavaScript 的『 λ 計算器Lambda Calculator。這個軟體是美國 Hendrix 大學計算機科學教授 Carl Burch 所寫,目的是提供『學習』和『實驗』λ 運算的有用之『工具』,它包含了『應用』與『純粹』λ語言等等的『客製化』選項。

LambdaCalculator
圖一

LC關於
圖二

LC選項化約過程
圖三

LC基本用法
圖四

lcex1lcex2
圖五

LC字典定義
圖六

LC字典
圖七

LC字典用法
圖八

左圖一是剛進網頁時的主畫面。其中『LC簡介1』是存放『 λ 表達式』的『字典』;『LC簡介2』是客製化『選項』;『LC簡介3』是軟體線上『使用說明』。一般的操作是由『 λ 表達式輸入列LC簡介4』,以及『執行 LC簡介5』與『清空輸入列 LC簡介6』所完成的。它之『主要』選項預設的是︰

☆應用 λ語言
☆使用 \eta 變換

此處我們先用《之前》的例子

((\lambda z. (( \lambda y. y + 1) (( \lambda x. x^2)z)))3)

,給個用法之說明︰一、語法上『 λ 』用『 \ 』符號表示;二、使用『前綴的』四則運算函式。所以上式應當改成

((\ z. (( \y. (+ y 1)) (( \x. (* x x))z)))3)

。左圖五是輸入後執行的結果,通常不會顯示『運算過程』,只看得到圖五中的『上半部』;有一個 Show … Intermediate Steps 的按鍵,它可以用來顯示其間的『化約過程』,可見之於圖五中的『下半部』。如果我們從『數學』上因何定義一個『函數』的觀點來看,人們對一個函數的『興趣』,並不祇在『求值』而已,往往會包含它之『性質』的研究。要是自『程式』計算的角度來講,一般之所以會定義某個『函式』,也不會是僅為『一次』的使用,而是因為它『經常』被用到。為了能夠既『簡潔』又『容易』的建立『複雜』之表達式,這個軟體它提供了『 λ表達式』定義的引用『字典』,於是你可以將『常用』的表達式『命名縮寫』成為『標識符號』。比方說如何將上面的函數
(\ z. (( \y. (+ y 1)) (( \x. (* x x))z)))
命名為『MyFun』。如果你曾經注意到任何的『表達式』輸入後,假使按下『執行』鍵,畫面會出現『加入字典 LC簡介7』選項,這時你只需要將『MyFun 的命名』打入它的『輸入列』,然後按下『加入字典圖像 LC簡介8』就可以了,參見左圖六。

現在讓我們利用 MyFun 輸入下式︰

(/ (* (- (+ (MyFun 5) (MyFun 5)) (MyFun 5)) (MyFun 5)) (MyFun 5))

,對任何一個非零的數 a 來說, \frac {((a + a) - a) \times a}  {a} = a,所以上式的答案應該是『 (MyFun 5) = 26』。難道不該是這樣嗎?『確定的函式』與『相同的輸入』不是該產生『一樣的結果』的嗎?比方說一個傳回『當下時間』的函式『 date 』,你每次調用它的結果不會是相同的吧!在計算機科學中把 date  這類的函式稱為有『副作用』Side effect 的,然而並不是說有『副作用』就是『不好的』,date 函式的目的就是『那個副作用』。但是『副作用』有時又是『問題』的由來,設想出於不明的原因如果很多次『呼叫』call 『MyFun 5』後的傳回結果是『5, 6, 7, 8, …』,那麼上式的答案自然不一樣了,此時想要『除錯』可就『麻煩』的了!

那麼函式的『副作用』又是怎麼發生的呢? 設想用 x 變元代表『鍵盤輸入的數值』,這個表達式 ( MyFun \  x) 就是計算此時『 x 』的函數值。但是不管輸入是什麼樣的數,輸出又是怎麼樣的值,這個『表達式』都是『不變的』。也就是說因為 x 變元的值『』了,所以 ( MyFun \  x) 也就跟著『』了。然而所謂的『 x 變元之值』又指的是什麼呢?變元『記得』當下的『之值』,直到被『賦與』Assign 『新值』,從『圖靈機』的觀點來講,變元就是機器之『內部』與『外部』系統當下的『狀態』。假使說『純函式』Pure Function 是指函式在『相同的輸入』下,一定產生『一樣的結果』,那麼該函式必然是『沒副作用』的函式,而且『所有的變元』的狀態,在函式呼叫『前後』都該是一樣的。因此我們可以說 ( MyFun \  x) 是『純函式』,因為只要 x 變元的值是一樣的,計算結果就是相同的,而且計算過程中 MyFun 並不會更改 x 變元的狀態。『泛函式』functional 程式設計的『典範』paradigm 主要強調在於『純函式』的重要性,或許也是事出有因的啊!!