接
上一篇文章。自从昨天设计了
NativeX语言的泛型之后,今天又对昨天的草稿做了一下修改。设计语言的语法总是这样,首先对你自己的需求提出直接的解决方法,然后看看是不是有些新的概念跟其他概念可以合并起来变成更抽象的概念,而且又不会在实现上导致困难,也不会让编译器变的突然难写许多。经过了昨天晚上和今天早上的思考,我决定简化一下泛型的语法以及concept的内容。
首先说语法上的。上一篇文章在定义泛型头的时候采用了generic<type T1, type T2, concept C1, concept C2>这样子的语法。本着尽量减少关键字的原则,我决定去掉type,变成generic<T1, T2, concept C1, concept C2>。原因是concept关键字还能用来定义一个契约,而type则毫无用处。而且一个契约有了concept关键字作开头,也不会跟没有type关键字的类型参数混淆。
其次是concept。昨天定义了concept instance和concept series。其实总结到最后,concept instance无非就是concept series的一个特例。根据昨天的说法,把所有的instance都替换成series其实结果还是一样的。唯一的区别就是concept series不允许在既不是concept定义所在的Assembly也不是特化所涉及类型的Assembly里面出现它的一个特化。如果单纯去掉了concept instance的话显然会带来问题:我在AssemblyA处声明了一个concept Sortable<T>之后,没办法在AssemblyB处声明一个concept series IntSortable : Sortable<int>。因此某一些限制需要放宽一点:
1、concept series的原始版本可以在一个既不包含concept声明和也不包含涉及的类型声明的地方声明。
2、concept series的特化版本则必须出现在包含concept声明或者包含涉及类型声明的地方声明。
那么其实series关键字也不需要了,因此会获得下面的写法:
1 generic<T>
2 concept GSortable
3 {
4 bool LessThan(T a, T b);
5 }
6
7 generic<T>
8 instance Sortable : GSortable<T>
9 {
10 LessThan = BinaryLessThen<T>;
11 }
12
13 instance Sortable<int>
14 {
15 LessThan(a, b) = a < b;
16 }
operation和function的区分实际上没什么大的价值,如果你真的需要一个函数指针的话,那就在参数传进去好了。而且constant也没什么必要,因为constant实际上是operation的一个特例,只是使用的时候需要多写一个口号罢了。我们会看到上面定义concept其中的操作的两个方法:指定函数和指定表达式。如果制定了表达是的话,那么该表达式将会被内联(啊)。所以constant存在的价值也就不存在了。因此我们甚至连function、operation和constant的区分也消失了,所以在语法上更加得到了简化。
NativeX每一次引入一个新的特性的时候都是迫不得已而为之,而且一旦引入之后我总是力图将该特性设计成跟其他所有的特性正交。例如这里的泛型,所有的东西都可以加上泛型,譬如结构体、全局变量、函数、契约和契约实例。所有的东西都可以是非泛型的,也可以是泛型的。有时候我们的确需要定义一个非泛型的concept,这其实也不是什么大问题。
不过当前的语法还会遇到C++那经典的>>问题(一直到了C++0x才正式纳入标准- -b)。这个问题有三种解决办法,第一种是不允许写成vector<vector<int> >,第二种是允许写a>>b也允许写a> >b(中间有个空格),第三种是跟VC++一样一概支持。最后一个比较困难,第二个比较奇怪,第一个比较恶习。不过结合了各种因素之后,其实我觉得支持第二个倒是最简单的办法:你仍然可以写出漂亮的代码,而且你如果自己受得了a> >b而自己恶心自己的话,那也是你自己的事……
至于其它问题,NativeX没有逗号表达式,声明NativeX的变量需要加上variable关键字,声明NativeX的函数需要加上function关键字,所以全部迎刃而解。
posted on 2010-06-13 23:50
陈梓瀚(vczh) 阅读(2495)
评论(2) 编辑 收藏 引用 所属分类:
VL++3.0开发纪事