浅谈现代编程语言语法与标准库紧绑定现象
在C语言时代,语法与库的实现基本上是完全独立的。几乎所有的C语言标准库都是与编译器实现相对独立的,仅与当前系统环境耦合。这里只有函数不定参数的实现是需要根据语言规范,结合当前系统环境,由库<stdarg.h>自己实现的。
C++98也基本如此。我们可以看到typeid是以关键字的形式出现的。尽管它返回一个类的对象,我们可以用typeid(expr).name()来访问表达式expr的类型名,不过它仍然可由编译器全权负责实现。
而Java作为半动态语言,它就已经把自己的库与语法融合在了一起。我们可以看到在Java中对字符串String对象的操作可以简单地使用操作符+、+=进行操作。然而String本身并不是关键字,但是可被编译器识别。因为你换成其它对象可能就无法用这些操作符来进行操作了。而对String类的实现本身可用一个用Java编写的相对独立的库进行实现。
所以,我们可以看到现在很多编程语言都采用了编译器与自己的标准库相互负责的模式进行实现,这两者被逐步融合。
这一点在Objective-C中也十分明显,比如我之前写的《Objective-C如何自己实现一个for-each语法形式》以及《Objective-C如何自己实现一个基于数组下标的属性访问模式》。另外,比如编译器对属性(property)自动生成getter/setter方法有一定的命名规则,setter方法是前面加set,然后属性名的首字母大写;而getter方法则是与属性名完全一致。通过这种规则,开发者可以自己实现已被编译器生成的属性方法,从而重写相应的getter及/或setter方法。这种伎俩虽然不严密,但也简单实用,呵呵。
C++11中这个特点也被凸显出来了。我们可以看到,通过将std::initializer_list<>作为类的构造函数参数,我们即可通过{ }初始化列表来初始化一个类的对象。通过在自定义的类中实现返回值为std::iterator的begin()与end()函数,我们直接可以使用for-each的循环形式——for(type &t : iteratableObj){ }。
其实将语法体系与语言自带标准库绑定还是有不少好处的。首先,这容易被扩展,开发者可以根据自己的需求来自定义某些语法的行为。其次,对编译器而言可以减轻压力。某些运行时行为可以交给标准库进行实现。这样,编程语言可以比较方便地被打造成比较完备的语法体系。这种耦合也增强了编程语言的运行时能力,包括灵活性、可扩展性。