太极语言出世——比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实现的。
玄之又玄,众妙之门,无招胜有招,无为无不为。学习太极语言,你要学会忘记,与学太极门武功是一样的,要学会忘记,而不是记忆。
(未完待续)
太极元年四月二十日