太極語言出世——比C++更好的語言(續)
(一)先來說一些太極語言中的小技巧。
[a;b;str]=[1;0;"taiji"];
show([str;a;b;]);
猜猜,能看懂這段代碼嗎?
其實就是
a=1;
b=0;
str="taiji";
show(str);
show(a);
show(b);
這也是太極語言程式碼群組合機制中的,太極語言程式碼群組合機制中有很多很好玩很有趣的,我慢慢說。
int [a;b;c];
這是
int a;
int b;
int c;
int * [pa;pb;pc];
這是
int * pa;
int * pb;
int * pc;
比寫成int *pa,*pb,*pc;有趣吧。而且還避免了遺漏*;C中*做指標時的多義性在編譯器設計時也可以避免了。
[a1;*fc1(2);*p]=[a;b;c]=[1;2;3;];這個呢?
是
a1=a=1;
*fc1(2)=b=3;
*p=c=3;
有自己的編譯器真好,我願意怎麼寫程式就怎麼寫程式,這才叫自由!
這個程式碼群組合機制是我當年從並聯電路中想到的,那麼串聯,混聯呢?以後再說。
我先說一下設計原則。
[]中有;則為“並聯”,一句中若含並聯,則被預先處理成n條語句(n=並聯元素數)。
剛才的那個寫法可以實現cout,cin
比如:
cout([a;str;b]);
cin([a;str;b]);
你只要重載一下名為cout函數就可以了,當然還有一些其他的輔助操作。
關於串聯,混聯寫一個式子,猜猜是什麼意思?
[fc1;fc2](a)=[[a;a+b];c];
還有邏輯門,濾波器……一系列的非常有趣的東西。這些要用到太極語言中的編譯描述語言——無極語言,等以後再細說。
(二)太極語言比C++更強大,又比C更接近底層,又比Basic更易學。
其實我覺的如果C不設main函數,本來就比Basic更易學。我在用C/C++編程式時,感到在C/C++中有一些設計是挺不合適的。
在LISP中有句話說“一切都是函數”,C程式以函數為單位的設計形式也許就來自此。但我發現好像從C設計者Ken Thompson和Dennis M. Ritchie兩位前輩那裡開始就有點混淆兩個概念,函數定義與函數調用,以至於在C/C++中實現了函數自由調用但是卻忽略了實現函數自由定義。
在C/C++中函數可以嵌套調用但是卻不能嵌套定義(嵌套定義是挺重要的,代碼封閉後可以更好的實現代碼複用,避開了名字空間中的衝突),結果搞的很多C/C++程式員總想著寫“通用萬能的函數”,結果卻老是發生衝突,以至於後來有人專門指出不要這樣。但是這種思維模式形成的根源卻就在C/C++不允許嵌套定義函數上,這樣名字空間總是覺的太小了。
我認為C/C++中設計以main函數為入口是很不必要的,在太極語言中不設MAIN函數,太極語言是以第一句“有序語句”為進入點(有序語句的意思是“非定義語句”,有序語句順序的變化會影響程式啟動並執行結果,如變數函數類的定義就是“無序語句”,無序語句順序的變化不會影響程式啟動並執行結果)。快馬一鞭,為什麼我們不能想編個程式直接開始說話就行了?就想在一些更古老的編譯器如fortran中那樣。設定main函數有一個好處,是在串連時才體現的,這樣可以解決多檔案模組程式碼產生後的連結順序問題,還有一個好處是可以輕易的找到函數的進入點。但是有更簡單的辦法可以實現這些,在太極語言中直接找全域垣中的return 就是進入點,同時也把串連順序問題解決了。而且把整個全域垣看成是一個無名函數,那麼直接就符合LISP“一切都是函數”的思想。(空既是色),這樣設計編譯器時根本不需要多寫代碼,體現出來非常精緻美觀。而且還可以直接在代碼中就自己指定進入點——就是return 後的函數。
C為什麼設計成編一個程式必須要至少設計一個函數呢?以至於初學者還沒學呢就得先寫一個函數,如果不是這樣,我想學習C/C++就是比Basic更容易入門並更容易達到同等程度,其實我覺的本來C/C++是比Basic更易學的,就是讓一個main函數給擋住了。
也許當年Ken Thompson和Dennis M. Ritchie認為實現了函數嵌套調用就是實現了LISP“一切都是函數”的思想了(這是認為“一切都是函數”就是一切都是函數調用),結果就沒有做函數自由定義;但是在main函數問題上,卻又說編一個C程式必須要至少設計一個函數,C程式以函數為單位(這是認為“一切都是函數”就是一切都是函數定義)。就是在這個問題上Ken Thompson和Dennis M. Ritchie給弄混淆了。這也是因為lisp沒把這個問題講明確。
LISP中“一切都是函數”的思想我是非常欣賞的。在初期我做太極語言時,設計的語言格式到處都是小括弧,這種格式非常容易用遞迴的方式來編譯,就是“一切都是函數”,非常有趣,後來才知道竟然在LISP中就是用的這種格式。
那麼“一切都是函數”究竟是“一切都是函數定義”呢還是“一切都是函數調用”呢?其實是兩方面都包括的,都實現了才是“一切都是函數”的概念。雖然pascal做到了這一點,但是我非常不喜歡pascal中begin end文法。
以函數為單位就設個main函數,C中的這種方式後來影響到了其他的語言,到了物件導向出現後,說“一切都是對象一切都是類”,以類為單位,結果不管用著用不著,都要定義一個類,比如java,c#,其實是完全不必要的,現在也不再那麼神化OO了(其實很多時候面向過程反而是比oo更好的解決方案),但是即使要設計成“一切都是類對象”,把涵蓋程式的“空”本身看成是一個初始類不就可以了嗎?而且類的過度使用大大降低了代碼複用性。比如一些字串處理函數,本來用函數實現就可以了,若嵌入類中實現,用起來非常麻煩。
小巧組合是美麗的,盡量不要設計龐大死板的體系。
C++模板也是動輒要啟用一個新設的類,很多時候根本不必要,完全可以有更好的設計,更精簡的實現同樣的功能。在太極語言中的程式碼群組合機制是遠比C++模板優秀的機制,大家從我以前舉的例子中也看到了,這種程式碼群組合機制往往以極少的代碼就實現了C++模板需要很多代碼才能實現的功能,——很多C++模板代碼可讀性都是非常差的,C++模板總是通過類繞大彎子迷惑人,然後再以把別人迷惑住了為“光榮”,被迷惑的人再以去迷惑別人為“光榮”。太極語言中的程式碼群組合機制一上來就在代碼錶義性、可讀性、可複用性、可維護性上遠遠的超過了C++模板。太極語言程式碼群組合機制背後是有嚴謹的數學理論為基礎的。我先簡單的說一下,其實宏的能力本來就遠遠超出模板(你同意這個說法嗎?),只是宏卻被人忽視了幾十年,宏的能力遠沒被發覺,現在的宏稍微擴充一下就可以在很多地方超出模板,人們卻誤入模板之歧途。我可以預言在兩年之內C++界會重新認識宏的能力。毫不客氣的說,C++ Template設計的挺糟糕的,那代碼簡直不是給人看的。現在大家如果不是特別需要可以先不用花太多的時間在C++ Template學習上,大家現在看stl和boost的原始碼時是不是覺的不容易呢?那麼就別看了(當然純演算法問題除外,那是固定的),就在這兩年之內出現新的機制,(用現在的術語說,設計思路類似把macro和non-template貫通到一體),那是有良好的可讀性可維護性的,到時候再學也不遲。那時候你看看是不是就是太極語言程式碼群組合機制,呵呵。我相信st、lpm和C++標準委員會裡的人一定會接受太極語言面向概念與程式碼群組合機制的。
(三)()中的名字全函數名字空間可見。
在太極語言中是這樣設計的,()中的名字註冊進入首個含名字空間的母垣,若中間經過了不含名字空間的{}垣則進行名稱垣閉。
C++標準委員會不讓for後()中定義的變數在外邊用,我認為這是錯誤的(誰知道怎麼跟C++標準委員會聯絡?)。for()中定義的變數讓不讓在外邊用曾經是一個爭議挺大的問題.在太極語言中是這樣考慮的:
單獨從for本身考慮兩方面的意見不好確定,把目光放向全域.就是看()中定義的變數是否要全地區可見.
在太極語言中講究"做一件事情只要一句話",讓緊密關聯的代碼能寫在一句中.
比如下面的一個函數調用.
fc(&(int a));//原型為 void fc(int * p);
k=a;
所以必須讓()中定義的變數全地區可見.
在C/C++中你卻必須這樣寫,
int a;
fc(&a);
k=a;
違背了"緊密關聯的代碼能寫在一句中"這個原則.
舉具體例子對比一下:
太極語言:
FindFirstFile(pfindstr,&(WIN32_FIND_DATA wfd));
C/C++:
WIN32_FIND_DATA wfd;
FindFirstFile(pfindstr,&wfd);
太極語言:
m_edit1.GetWindowText(CString cstr);
m_edit2.SetWindowText(cstr);
C/C++:
CString cstr;
m_edit1.GetWindowText(cstr);
m_edit2.SetWindowText(cstr);
(要是寫成[m_edit1.GetWindowText;m_edit2.SetWindowText](cstr);你猜是什麼意思?)
太極語言:
FindFirstFile(char * pfindstr="*.*",&(WIN32_FIND_DATA wfd));
C/C++:
char * pfindstr="*.*";
WIN32_FIND_DATA wfd;
FindFirstFile(pfindstr,&wfd);
從代碼的可讀性與直觀性與可維護性上太極語言所採用的方式是比C/C++好的.
需要預定義的變數增多時這種表現更明顯.必須讓()中定義的變數全地區可見!
那麼從形式連貫一致性角度考慮,也要讓for()中定義的變數全地區可見!
即使僅從"緊密關聯的代碼能寫在一句中"這個原則考慮,也應該讓for()中定義的變數全地區可見!
在太極語言中是這樣設計的,()中的名字註冊進入首個含名字空間的母垣,若中間經過了不含名字空間的{}垣則進行名稱垣閉。
(四)為goto辯護
goto 是最自由的,最自由的一定是威力最強大的,
在這個到處充滿了結構化物件導向軟體工程的時代,這種自由在慢慢被剝奪,goto 一次又一次的受到批判,但是goto 仍然頑強的活著,其實看看C++之父的書中是怎麼頑強支援GOTO的?難道結構化標準化真的那麼重要,竟值得用剝奪程式設計的自由去換取!雖然while和if可以代替goto 實現功能,但是有時卻不可避免的破壞了表意直觀性與可維護性,特別在一些高度複雜的狀態下,goto是你唯一的選擇。goto能做到while,if能做到的一切,反過來卻不能。
說什麼goto,指標不安全,那電也不安全就都不用電了嗎?決不是這麼回事,威力強大的工具往往都是有一定危險性的,但並不能因此而禁用威力強大的工具。
在太極語言中不僅有goto,而且設計了增強功能的goto,goto(條件) 標號,而且標號還可以是一個變數。(變形代碼就是按這個原理實現的)
而且,在太極語言中,if,while,for,do..while,……全都是用代碼裝配技術和goto實現的。
玄之又玄,眾妙之門,無招勝有招,無為無不為。學習太極語言,你要學會忘記,與學太極門武功是一樣的,要學會忘記,而不是記憶。
(未完待續)
太極元年四月二十日