這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。
我並沒有去專門為了Lisp使用首碼運算式而去網上尋找鼓吹有關此方面的文章或書籍。我也並不是Lisp的狂熱愛好者。學習Lisp最初只不過是學習其偉大思想。
不過當我慢慢學過Lisp一段時間之後,我慢慢的發自內心的喜歡上了它。我用的是Scheme,一個教學用的語言。當然對於其使用的首碼運算式我也想說一下我自己的認識。
先說一點:首碼運算式也可以叫波蘭式,尾碼運算式也可以叫逆波蘭式。
上過資料結構課,我們都知道首碼、中綴和尾碼運算式分別對應的運算式樹狀架構的先序、中序和後續遍曆。也就是說首碼、中綴和尾碼運算式這三者可以互相轉換的。
比如:
- 中綴:1 + 2 + (3 + 4) 5 + 6 + 7
- 尾碼:1 2 + 3 4 + 5 + 6 + 7 +
- 首碼:+ + + + 1 2 * + 3 4 5 6 7
很多人是很不適應甚至反感首碼運算式的,因為很不習慣,我們從小學習數學,學習基本的四則運算,好像數學都是用的中綴運算式。真的是這樣子嗎!
其實不是的,在四則運算加減乘除以外的世界,其實都是用的首碼運算式,舉個例子,比如根號√4,這是在數學再常見不過的求根運算式了。它就是一個首碼運算式。
根號在最前面。當然根號是個一元運算子,根號裡面的被視為一個整體,對整體求值。
在舉一個例子,比如令許多人頭疼的積分∫。它也是首碼運算式,積分符號∫在各個參數的最前面。
現在看來,數學書上就是在用首碼運算式,大家也都可以適應,為什麼到了編程中就不怎麼適應了……
<hr>
當然更坑爹的是逆波蘭式:比如Pascal中定義變數var x : real;
或者近來的年度語言Golang的定義變數var x float。(順便說一句,之前看過王垠的部落格,它也不喜歡go的這種定義變數方法)
大家習慣的是比如double x;這樣子的定義變數方法。
當然有些時候,在處理二元關係的時候,無論是波蘭式還是逆波蘭式都沒有中綴運算式好理解。就比如我們的四則運算,只不過是把加減乘除當作了特殊的運演算法。
也就是只能處理二元關係的運算子(這裡的是減號而不是負號--一元運算子)。
除此之外呢,比如函數f(x . y),這個樣子寫是表示函數f中可以有多個參數。也就是C語言中的f(int... a)可變參數。
如果我們把函數f當作是一個運算子,其實它可以是運算子或者是它就是運算子,因為它處理了參數。函數就是一個採用首碼的表達方法。
因為如果你不用首碼你怎麼寫出運算式呢?比如要定義x,y,z這三個參數的和的函數,sum(x, y, z),如果用中綴你如何寫出運算式呢?
(x sum y) sum z 這個樣子嗎?這個樣子好像也停坑爹的。也就是說首碼可以支援任意多的參數,而中綴只能支援兩個。因為到了多元關係之後,中綴幾乎不存在
這樣的表示方法,根本沒有可比較的對象。
所以當處理非二元關係的時候,首碼運算式還是有一些優越的。另一點,如果這個operator的名字比較長,放在前面會好看一些。(竊喜
當然使用首碼運算式可以與函數表示方法相統一。這個樣子,就可以使得很多事情變得和諧,統一。
說了這些,其實首碼中綴最大的分歧在於二元關係上,如果二元關係出現的多,那就使用中綴運算式,如果多元關係出現的多那就使用波蘭式。