泛型编程的困境

时间:2022-06-21 16:06:24

原文:http://research.swtch.com/generic

常用的数据结构(vectors,queues,maps,trees,等等)似乎是评估一个新语言的一个热门话题。Go语言的FAQ中有一条就是关于Go中的泛型编程。对于泛型编程的通常有以下三种处理方式:

1.(C语言)放弃泛型。这样苦了程序员,但是这样没前增加太多复杂的东西到语言中。


2.(C++语言)编译期特化或者大量地展开代码。这样苦了编译器。编绎器生成一堆代码,而大部分是无用的,需要一个很好的链接器去清除重复的副本。为每一个类型生成一份代码,也许这样会让代码高效,但是程序是一个整体,这样会造成对cpu的cache不友好。我曾听说一个简单的库修正和移除了模板后,text段(即动态链接库的文件格式中的text段)的大小从M级降到10K。

3.(Java语言)隐式地把所有东西装箱。这样苦了程序,这样执行起来会变慢。
对比C语言的手写,C++语言的编译器生成,Java代码最简单,但是最低效,无论是从时间还是空间来说。因为所有的操作都要隐式地装箱和拆箱。一个byte的vector容器(Vector<Byte>)所占的空间比远超一个字节每一个byte。想要隐藏装箱和拆箱会让类型系统变复杂。从另一个方面来说,这个也许是指令cache友好的,因为它把一个byte的vector(Vector<Byte>)可以分开来写每一个byt e。


泛型编程的困境是:要么苦了程序员,要么苦了编绎器,要么降低运行时效率。


=====================================================

原文作者是Go语言的实现者之一。

从Go的FAQ中也可以看到他们并不急于去实现泛型,是因为还没有找到一个合适的实现方案去解决上面的困境。

因为Go目前没有泛型,所以只能用interface来实现常用的数据结构了。但是从我个人角度来看Go中的interface的效率有点慢(比C++中的虚函数要慢,想想一个Vector容器,调用一个get函数,都比调用C++的一个虚函数还要慢。。)。

所以在Go1.0之前,有Vector容器时,另外还有一个IntVector和一个StringVector。想想有够蛋疼的,如果我想用一个高效float的Vector,是不是还要写一个FloatVector?

如果Go能支持泛型,那真是相当令人高兴的一件事。