The Case for D —硬币的另一面

The Case for D —硬币的另一面

作者:leonardo(leonardom)
翻译:尚波

Andrei Alexandrescu 已经写了一篇好文章:《The Case for D》。


D1是个很好的语言,我经常使用它,但是这篇文章显示出太多D2语言和它的编译器的好处,主要聚焦在它将来可以做什么上,而忽略了当前存在的一些消极面和问题。给新有D用户提供虚假期望是危险的。我认为给出现状的一个更平衡的叙述会更好,即使在将来大多数当前的D问题可以被修正。


一篇好文章必须显示当前语言中存在的困难,而不仅仅是谈论若干年后可以看到的良好实现。目前Java是非常快的语言,编译器可以帮助程序员避免许多可预见的bug,并且工具链也非常完善。但是在Java开始的时候它非常慢,实用性也很有限,只不过是一个玩具而已。


这篇邮件不是我在D语言中见到的所有缺点的列表,它仅是关于Andrei Alexandrescu的文章的注释的列表。
从该文中:


“在开发过程中,语言复杂性有所增加,这实际上成了一个好的标志,因为没有哪个实际使用中的语言会变得很小。”


D2语言比D1更复杂,即使添加到D中的每样东西都有它的正当理由,c++语言清楚地表明,太多的复杂性并不是一件好事。因此过高的复杂性并不是一个很好的指标。

 

 

“其他的实现还没有完成,著名的包括一个.NET移植和使用LLVM基础设施作后端的编译器(译者注:ldc)。”


LDC编译器(使用LLVM后端)在Linux上和Tango标准库(缺乏内建的分析器)已经可以编译D1的代码。在Windows平台,LLVM缺乏异常支持,因此还不可用。

 

 

 

 

“D可以说成是最好的高级系统编程语言。”


很难想象用D去写像Linux内核这样的东西或去写诸如嵌入式系统的代码。对于嵌入式系统那只有几千字节的内存D编译的程序显得太大,D语言对GC的依赖太多以致于不能成为写现实生活中的内核的一个好工具。


所以D语言更像一个类系统编程的语言。一个多层次的语言,可以用来写接近于“金属”(Metal,注:可能是笔误,应为Meta)的代码相当接近“金属”或者也可以写高级通用的代码。

 

 

 

 

“它包含的特性可以正常地在高级语言甚至脚本语言中找到—如快速的编译-运行周期。”


在D中由编译后的模块做成的程序,其编译-运行周期可同C#和Java一样快。

 

 

 

 

“事实上,D可以直接链接和调用c函数而不需要要中间翻译层。”


在Windows上你必须用DMC编译C代码来做到这一点。

 

 

 

 

“不过,你很少感到强迫自己去用低级语言,因为D自己的设施更强大、安全和有效率。”


目前,在实践中存在一些使用C风格代码比D1的性能更高的情况(特别是使用DMD编译器而不用LDC时)。

 

 

 

 

“内建支持文档和单元测试。”

 

这样的东西非常方便也非常好。但目前对文档的内建支持有很多bug,并且内建的单元测试非常原始和有限:例如测试没有名字,他们只包含了正常的代码和断言(assert()),一旦第一个断言失败运行就停止。


如:
return printf("hello, world\n") < 0;

 

 在C中可能更正确:

if (printf("hello, world\n") >= 0) return EXIT_SUCCESS; else return EXIT_FAILURE;
 
  

 

 


(and T!(X) or simply T!X for T<X>)


在D1中不支持T!X语法。在D2中存在另一个规则,你不能把
T!(U!(X))写成T!U!X
这个例子显示d2更复杂,它要保存两个字符。

 

 

 

 

“D的编译、保护、模块化单位是文件。包的单位是一个目录。”


D的模块系统是很好很方便,但它现在有一些bug,并具有一些语义漏洞。


留给程序员的感觉是开头设计得好,但中段的开发设计已经停止,留下一些未完成的功能。例如,如果你导入模块“foo”,在当前命名空间中它导入的不只是“foo”,而是所有包含在“foo”中的名字和“foo”自身。这是愚蠢的。


循环导入语义、包语义和安全性也存在一些问题(缺乏从一个模块中导入所有名称的语法。把从一个模块中导入所有名称作为默认行为是糟糕的。)


另一个不利的是,所有现存的D编译器不能自己跟踪模块树以编译代码,因此你需要告诉编译器你要编译的所有模块,即使这样的信息已经完全呈现在代码本身里。有几种工具试图补充这个基本功能的漏洞(非常大的程序需要更复杂的策略,但经验告诉我们大部分很小的D程序可以用自动编译模型很好的处理)。

 

 

 

 

“一、语言的语法允许单独分解、解析以得到高度的优化。”


这也有坏处,它限制了在语言中有可能使用的语法,例如它使这个代码不可能 foreach (i, item in items)

 

 

强制语言要这样使用,就减少了一些可读性,增加了一些可能的bug:

foreach (i, item; items)
 

 

 

 

“三、Walter Bright,D语言创造者和最初实现者,是一个资深的优化专家。”


这可能是真的,尽管DMD后台会产生不太高效的代码。LDC(LLVM后端)在当前通常更好。

 

 

 

 

“其他面向对象的编程语言只有小的改进,”


不真实,看看Clojure和Scala。但愿D会做得更好。

 

 

 


“函数式语言的兴盛是一个大趋势”


更多的人在谈论文艺复兴:-)

 

 

 

“SafeD集中在消除内存崩溃的可能性。”


也许更的是把其它的安全性添加到 SafeD这样的模块中。

 

 

 

 

“这使得Java和c#代码非常易于移植到D实施的工作上。”


这的确很容易地移植C/Java代码到D。但转换C头文件到D需要一些工作。当前D的垃圾收集器没有Java通用的那个有效率,因此D需要更少分配的代码。

 

 

 

 

“显式override关键字避免意外的覆盖。”


它是可选的。

 

 

 

 

“有一个技术我不能提到,因为它是有商标权的,因此让我们叫它契约式编程(contract programming)。”


它是内建在语言中的。虽然没有完整实现,但如果你没有把它用到埃菲尔铁塔( Eiffel)上的话已足够了。


“现在的实现带有O(n)time和尾部调用优化(tail call optimization),要注意空间复杂性”


目前只有LDC(一个d1编译器)可以执行尾部调用消除(tail-call elimination),并且只能在简单的情形下。不过随着LLVM的改进,LDC也会改进。

 

 

 

 

“当迭代是首选方法时,iron-clad 功能纯正的保障和舒适地实现,如果不是太酷了,我不知道它是什么。”


目前不能在循环外部调用纯函数( pure functions)。如果纯函数产生一个内存溢出异常或涉及到浮点舍入模式的改变时,就可能存在一个问题。


函数式编程巧妙地处理大量不可变数据,这样会使垃圾收集器有很大的压力。当前D的GC对于这样快速的内存分配周期效率不足,因此它不适合函数式编程或Java风格那种频繁分配的面向对象编程风格。


所有的这些不是要阻拦你使用D1/D2语言。

 

 

 


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值