Random Stuff from GlacJAY

Haskell 中的可变长参数列表

说实话,我之前有就这个题目很有激情地写了很长很罗嗦的一篇草稿的,哦,确切来说是大半篇,直到被打断,激情不再,这篇草稿也就此躺了两个多月。好吧,其实是我还不是八卦那块料,就不卖弄了,直接总结。

要在 Haskell 中实现可变长参数列表,就是利用其 Typeclass 系统,对函数进行最终结果类型和中间函数类型之间的重载,然后利用 Haskell 的类型推导机制为我们自动调用合适的重载版本。嗯,就这么简单。下面是一个最简单的例子:

有关 C/C++ 中的 do { ... } while (0) 惯用法

C/C++ 中的宏是个让人又爱又恨的家伙(感觉这句话好俗啊),在带给我们很强大的 Power 的同时,却也需要我们绝对的细心,而这也是在宏定义中诸多惯用法的由来。

当我们要把一组语句定义成一个宏,并希望像用一条语句那样来使用它的时候,我们就可以这样做:

C++ 中的纯虚析构函数与抽象类

我以前只知道,在 C++ 中,如果要表示一个类是抽象基类,只要为它定义一个纯虚析构函数就可以了,没想到今天用到的时候才发现,连接的时候通不过,说没有找到那个函数的定义。到网上一搜才知道,原来纯虚函数也是可以有定义的啊。在实现文件中加上它的空定义之后,一切就 OK 了。

不过,因为我那个基类里面已经有了一个纯虚函数,所以貌似没必要把析构函数也定义成纯虚的。

PS. 在 C++ 里面要实现 AST 还真是一件麻烦的体力劳动,要写那么多类,每个类还得写那么一砣的样板代码。幸好不是那种长期运行的服务器程序,不需要太考虑 memory leak 的问题,就不用写析构函数和 delete 了(实际上是懒得写),不然样板代码还要更大砣。不知道有什么更好的方法没。

Bison 中的 Prologue 的格式变迁

今天在用 Bison 手册中的 C++ 例子作为一个编译器前端实现的起点时发现,这个官方示例居然编译通不过,具体错误为在 Bison 生成的头文件中,没有 Driver 类的声明。按照 POSIX Yacc 标准,位于 %union 块之前的 Prologue 区中的代码,应该会被拷到头文件中的啊,于是 google 半天,在某个地方的 Bison ChangeLog 中找到了线索。

原来,POSIX Yacc 确实应该符合上述行为,可是 Bison 这家伙为了统一性,从 2.3a 版开始,就把所有 Prologue 中的代码,不管是 %union 前的还是之后的,统统只拷到实现文件中而不管头文件了。而为了对应不同的需求,又新增了一套 Prologue 语法,就是 %before-header 等四个新的 directive。好吧,这样也不错,以显式的统一格式的声明代替了可能会让人抓狂的隐规则。遂试之,结果告诉我说语法错误。接着往上看 ChangeLog 才发现,到了 2.3b 就又改了,把 %before-header 改成了 %code 之类的。这回终于没问题了。

我说,这也太不厚道了吧,这种兼容性改动,我在它的文档里面扒了半天都没看到半个字,而且还是出现在流行度这么高的软件中。于是深刻体会到「错文档不如无文档」的道理啊。由此看来,要做好软件还是需要有相当的责任感的啊。