`

The Case for D - the other side of the coin

阅读更多

The Case for D - the other side of the coin

作者leonardo
(leonardom)

Andrei Alexandrescu has written a nice article, "The Case for D" (click on 'Print' to read it on a single page):
http://www.ddj.com/hpc-high-performance-computing/217801225

D1 is a very nice language, and I use it often, but this article shows too much the good sides of the D2 language and its compilers, focusing on what it may do in future, ignoring their numerous current downsides and problems. Giving false expectations in possible new D users is dangerous. I think that giving a more balanced account of the current situation is better, even if in future most of current D problems may be fixed.

A good article must show the current troubles of the language too, and not just talk about good implementations that may be found years from now. At the moment Java is a very fast language, the compiler helps the programmer avoid many bug-prone situations, and the toolchain is very good. But at the beginning Java was really slow and of limited usefulness, it was little more than a toy.

This post isn't a list of all faults I see in the D language, it's a list of comments about the article by Andrei Alexandrescu.

From the article:

>In the process, the language's complexity has increased, which is in fact a good indicator because no language in actual use has ever gotten smaller.<

D2 language is more complex than D1, and even if each thing added to D may have its justifications, C++ language clearly shows that too much complexity is bad. So higher complexity is not a good indicator.


>Other implementations are underway, notably including an a .NET port and one using the LLVM infrastructure as backend.<

The LDC compiler (with LLVM backend) is already usable on Linux to compile D1 code with the Tango standard lib (but it lacks the built-in profiler). On windows LLVM lacks exception support, so it can't be used yet.


>D could be best described as a high-level systems programming language.<

It may be quite hard to think about using D to write something like the Linux kernel, or to write code for little embedded systems. D compiled programs are too much big for embedded systems with few kilobytes of RAM, an the D language relies too much on the GC (even if it can be switched off, etc) to be a good tool to write real-world kernel.

So D is currently more like a systems programming-like language. A multi-level language that can be used to write code quite close to the 'metal' or to write high-level generic code too.


>It encompasses features that are normally found in higher-level and even scripting languages -- such as a rapid edit-run cycle,<

Being made of compiled modules, the edit-run cycle in a D program can be as fast as in other languages like C# and Java.


>In fact, D can link and call C functions directly with no intervening translation layer.<

On Windows you usually have to compile the C code with DMC to do this.


>However, you'd very rarely feel compelled to go that low because D's own facilities are often more powerful, safer, and just as efficient.<

In practice currently there are situiations where using C-style code can lead to higher performance in D1 (especially if you use the DMD compiler instead of the LDC one).


>support for documentation and unit testing is built-in.<

Such things are very handy and nice. But the current built-in support for documentation has many bugs, and the built-in unit testing is very primitive and limited: for example tests have no name, they just contain normal code and assert(), and their running stops as soon as the first assert fails.


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

This may be more correct C:

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


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

In D1 the T!X syntax isn't supported. In D2 there's another rule, you can't write:
T!(U!(X))
As:
T!U!X
This is an example where things are more complex in D2 just to save two chars.


>D's unit of compilation, protection, and modularity is the file. The unit of packaging is a directory.<

D module system is nice and handy, but it currently has several bugs, and it has some semantic holes.

The sensation it leaves in the programmer is that its design was started well, but then the development of such design has stopped mid-course, leaving some of its functionalities half-unfinished.

For example if you import the module 'foo', in the current namespace it imports not just 'foo', but all the names contained into 'foo', and the 'foo' name itself. This is silly.

There are also troubles with circular import semantics, package semantics, safety (it lacks a syntax to import all names from a module. That's the default berhavour, and this is bad).

Another downside is that all current D compilers aren't able to follow the module tree by themselves to compile code, so you need to tell the compiler all the modules you need to compile, even if such information is already fully present in the code itself. There are several tools that try to patch this basic functionality hole (very big programs need more complex building strategies, but experience shows me that most small D programs can be fine with that automatic compilation model).


>* One, the language's grammar allows separate and highly optimized lexing, parsing, and analysis steps.<

This also has the downside that it limits the possible syntax that can be used in the language, for example it makes this code impossible:
foreach (i, item in items)
Forcing the language to use this, that is a bit less readable and a little more bug-prone:
foreach (i, item; items)


>* Three, Walter Bright, the creator and original implementor of D, is an inveterate expert in optimization. <

This is probably true, despite this the backend of DMD produces not much efficient code. LDC (LLVM-backend) is generally much better in this.
Update1, Jun 17 2009: DMD (especially DMD D1) is faster than LDC in compiling code.


>Other procedural and object-oriented languages made only little improvements,<

Untrue, see Clojure and Scala. Hopefully D will do as well or better.
Update1, Jun 17 2009: both Clojure and Scala run on the JVM, so the situation is different.


>a state of affairs that marked a recrudescence of functional languages<

Some other people may talk about a reinassance, instead :-)


>SafeD is focussed only on eliminating memory corruption possibilities.<

It may be better to add other safeties to such SafeD modules.


>That makes Java and C# code remarkably easy to port into a working D implementation.<

It's indeed quite easy to port C/Java code to D. But translating C headers to D may require some work. And currently the D garbage collector is much less efficient than the common Java ones, so D requires code that allocates less often.
Update1, Jun 17 2009: there are tools that help convert C headers to D.


>such as an explicit override keyword to avoid accidental overriding,<

It's optional.


>and a technique I can't mention because it's trademarked, so let's call it contract programming.<

It's built-in in the language. It's not implemented in a very complete way, but it may be enough if you aren't used to Eiffel.


>The implementation now takes O(n) time, and tail call optimization (which D implements) takes care of the space complexity.<

At the moment only the LDC compiler (a D1 compiler) is able to perform tail-call elimination (and probably only in simple situations. But probably as LLVM improves, LDC will improve).
Update1, Jun 17 2009: I was wrong, DMD is able to tail-call optimize if the situation is simple.


>iron-clad functional purity guarantees, and comfortable implementation when iteration is the preferred method. If that's not cool, I don't know what is.<

At the moment calls to pure functions aren't moved out of loops. There can be problems if the pure function generates an out of memory exception, or if it's involved a change in the floating point rounding mode.

Functional programming juggles lot of immutable data, and this puts the garbage collector under a high pressure. Currently the D GC isn't efficient enough for such quick cycles of memory allocation, so it's not much fit yet for functional-style programming (or Java-style Object Oriented style of programming that allocates very frequently).

All this isn't meant to discourage you from using the D1/D2 languages.

-------------------------------

Update1, Jun 17 2009:
See also the discussion on Reddit:
http://www.reddit.com/r/programming/comments/8t7s1/the_case_for_d_the_other_side_of_the_coin/

Answers to the received comments:

Thank you Anonymous for your large amount of comments. I'll fix the blog post where I see it's necessary. Your comments will help me a lot in improving my blog post.


>For exception support, it's more C++'s LLVM and Windows SEH issue, to get it right.<

Eventually LLVM/Clang developers will support exceptions on Windows. Several things tell me that LDC will be a good compiler.


>As for profiler, I believe you can compile to LLVM bytecode and profile that by LLVM tools, but well, it's ugly.<

Some things are already possible (I am trying KCachegrind now), but DMD is quite more handy, you can just add a "-profile" and it just works. (Code coverage of DMD too is handy, but it doesn't work on some bigger programs of mine). Walter has said more than one time that having easy to use tools helps people use them more often.


>but what we actually want are just more tools and more mature tools.<

Command-line features like DMD profiler are enough for me in many situations.


>Well, there is actually microkernel OS in D around:<

I know, but I have read an half-serious proposal to create another compiler to compile the Linux kernel because GCC isn't too much fit for this purpose. So I guess D compilers too may be even less fit for that purpose.
On the other hand Microsoft is trying to use a modified C# to write a OS (and they say the extra safety offered by C# allows to avoid some controls in the code, and this ends up creating globally efficient enough code), so it may be doable in D too.


>D programs are somewhat bigger minimal C apps (and esp., compiled by LLVM LDC) because of 3 things:<

A GC can't be avoided, but maybe it's possible to keep it outside, dynamically linked.
The runtime contains unicode management, associative arrays, dynamic arrays and more, but it may be possible to strip away some of such things when not used.


>(as a example of such multi-level language, but I'd like to see OMeta-like stuff for D better).<

OMeta is the future :-)
See also Pymeta, Meta for Python:
http://washort.twistedmatrix.com/


>Exactly, but you always can reimpement your wheels (read: modules/packages via classes, and some design pattern around that), and feed them thru CTFE/mixins.<


I'd like the built-in unittest systems to be a bit more powerful, or you can of course re-implement them outside the language, but then it's better to remove the built-in unittest features. Keeping both is not good.


>That's actually matter not compiler itself, but your build system.<

The DMD compiler already has built-in things that are beyond the purposes of a normal compiler. Adding this automatic build feature isn't essential but it's handy and positive.


>Hey, that 'item in items' stuff is not D semantic, and has nothing to with compiler itself.<

D compiler is designed in several separated layers. So it seems that to change the syntax adding an "in" inside the foreach you have to add some feedback between layers, and this is seen as bad for the compiler (and probably Walter is right here).


>public/private import?<

Imports are already private by default now in D. The problems are quite more big here.


>new instaneous dee0xd<

Never seen that before.


>Arguable: dmd still compiles faster, and binary sizes are smaller. LLVM optimizations are much more promising, though.<

In most of my benchmarks LDC produces programs that are faster or much faster. DMD indeed compiles faster (DMD of D2 is a bit less fast). Binary sizes produced by LDC are sometimes bigger but they are working on this, and most times the size is similar.


>Somewhat different playgrounds here: JVM-based or self-hosted.<

You are right, the situation is different. But I think you can implement Clojure multiprocessing ideas even without a VM.


>Just stub your own GC in. There are different GC strategies after all, why to hope 'one size fitts all' on every cases?<

Indeed, JavaVM ships with more than one GC to fulfill different purposes.
My own GC is probably going to be worse than the current built-in one. I am not able to write a GC as good JavaVM ones. So what you write here is not good.


>Java GC's was much worse than Oberon's btw, when it just appeared.<

Java at the beginning was WAY worse, I know, I have stated this at the beginning of my blog post.


>And if you have many of 'quick cycles of memory allocation', something is wrong with your memory allocator. It's not better when you have lotso manual malloc/free, its better when you have memory pools, arenas, zones, and right allocation (or GC) strategy, which fits better for you app.<

If you look at most Java programs you can often see many small objects allocated in loops.
At the same way, in functional-style languages/programs you can see lot of immutable data structures that are created and collected away all the time. From my benchmarks I think the current D GC isn't fit for such kinds of code.


>So I believe we can't rely on one single GC for all use cases, but we need lotso strategies and pluggable GC's for different uses cases and different strategies.<

I agree, but probably 2-3 GCs (built-in and switchable at compile time) can be enough for most D purposes. I am sure there are many ways to improve the current D GC (for example having a type system able to tell apart GC-manages pointers, and a hybrid moving\conservative GC that pins down memory manually managed, and moves and compacts all the other memory), my purpose was just to show and talk about the current situation.


>That shouldn't stop you in any way from using D<

Of course. I don't waste hours of my time commenting about a language I don't like to program with :-)
D is my second preferred language (after Python), I like it and I have written lot of D code :-)

Thank you again for all your comments, as you see I agree with most of the things you have written here.

分享到:
评论

相关推荐

    Coin-3.1.3-SoWin-1.5.0-vs2008

    《Coin-3.1.3-SoWin-1.5.0-vs2008:在Visual Studio 2008中的3D图形编程实践》 Coin是一个强大的三维图形库,它是Open Inventor的开源实现,广泛应用于科学可视化、工程设计、虚拟现实等领域。这个名为“Coin-3.1.3...

    Test bias: The other side of the coin

    Test bias: The other side of the coin Ptvchology in rhe Srhoulr 1981. 18. 450-454 TEST BIAS: THE OTHER SIDE OF THE COIN' JOHN H . ROSENBACH Slate University ofNew York at Albany BARBARA A. ...

    coin-or-Clp-devel-1.16.10-1.el7.x86_64.rpm

    coin-or-Clp-devel-1.16.10-1.el7.x86_64.rpm

    coin-or-Cbc-devel-2.9.8-1.el7.x86_64.rpm

    coin-or-Cbc-devel-2.9.8-1.el7.x86_64.rpm

    Coin-3.1.3

    books exists on the subject of Open Inventor, most notably The Inventor Mentor, and The Inventor Toolmaker, both highly recommended for those who wants to learn how to use Open Inventor.

    Coin-slider-master

    "Coin-slider-master" 是一个可能与网页开发相关的项目,标题和描述都反映了这一点。这个项目的重点可能是实现一种基于Coin Slider的交互式元素,这通常是一种动态展示图片或内容的滑动展示组件,常用于网站的轮播图...

    Coin-3.0.0-bin-msvc6.zip

    首先,"Coin-3.0.0-bin-msvc6.zip"是一个包含Coin3D 3.0版本的库文件和相关资源的压缩包,特别针对VC6.0编译环境进行了优化。在解压后,我们可以看到四个主要的文件夹:data、bin、include和lib。 1. **data** ...

    Bluetooth Low Energy The Developer-'s Handbook.pdf

    Running on a single coin-sized battery, BLE can run for years, connecting and extending everything from Personal Area Network devices to next-generation sensors. In Bluetooth Low Energy, one of the ...

    coin-or-Cbc-2.9.8-1.el7.x86_64.rpm

    coin-or-Cbc-2.9.8-1.el7.x86_64.rpm

    前端项目-coin-slider.zip

    【前端项目-coin-slider.zip】是一个包含jQuery图片滑动插件的前端开发资源包,名为"coin-slider"。这个插件的独特之处在于它提供了独特的图片切换效果,为网站的图像展示带来动态和交互性的增强。在本文中,我们将...

    Coin-3.1.3-SoWin-1.5.0-vs2010

    《Open Inventor在Windows平台上的实现:Coin-3.1.3与SoWin-1.5.0在Visual Studio 2010下的编译详解》 Open Inventor是一款强大的三维图形开发库,广泛应用于科学可视化、CAD以及游戏开发等领域。在Windows操作系统...

    Coin3D-Qt.PDF

    《Coin3D-Qt.PDF》是一份详细探讨Coin3D与Qt集成的文档,它主要阐述了如何在Qt应用程序中利用Coin3D库来创建3D图形界面。Coin3D是一个开源的3D图形库,它实现了OpenInventor API,而Qt则是一个广泛使用的C++图形用户...

    The-coin-collection

    标题"The-coin-collection"可能指的是一个关于收集、管理或处理虚拟货币的项目,或者是某种形式的游戏或应用。在这个项目中,JavaScript可能是用于实现用户交互、数据处理以及后端通信的关键技术。 1. **JavaScript...

    coin3D-3.1.3-SoQt-SoWin-VC10.7z )

    Coin3D是一个开源的三维图形库,主要用于构建交互式的3D应用程序。这个“coin3D-3.1.3-SoQt-SoWin-VC10.7z”压缩包包含的是Coin3D的3.1.3版本,适配于Qt和Windows平台,且是用Visual Studio 2010 (VC10) 编译的...

    duino-coin-auto-updater:Duino-Coin自动更新器。 检查https

    已淘汰 Duino-Coin自动更新器 ...tar zxvf duino-coin-auto-updater.tar.gz 导航到您刚刚提取的文件夹 cd duino-coin-auto-updater-1.0.0 并启动它! ./duino-coin-auto-updater 视窗 只需启动.exe文件

    Coin3D-Qt.zip_Coin3D_Molongcoin-qt代理_qt-coin3d

    《Coin3D与Qt结合开发详解》 在IT行业中,跨平台的图形用户界面(GUI)开发是一项重要的任务,而Coin3D与Qt的结合应用则为此提供了强大的解决方案。本资料主要围绕“Coin3D-Qt.zip_Coin3D_Molongcoin-qt代理_qt-...

    Practical Quantum Computing for Developers

    You’ll peak inside the inner workings of the Bell states for entanglement, Grover’s algorithm for linear search, Shor’s algorithm for integer factorization, and other algorithms in the fields of ...

    Coin3D-3.1.3-all

    Coin3D是一个开源的3D图形库,主要版本为3.1.3,适用于Linux、Windows和Qt平台。这个库提供了强大的三维图形渲染能力,旨在支持Scene Graph API,类似于OpenGL的面向对象接口,使得开发者可以更高效地创建复杂的3D...

    jquery图片自动轮播插件coin-slider

    jQ的插件呢确实很多,要做网站首页的图片切换的功能也有很多,找了很久,找到了一个自己觉得最华丽的。该插件切换的效果有如ie的滤镜效果一样炫...您也可以在这个地址去访问http://workshop.rs/projects/coin-slider/。

    Coin3D,Coin-3.1.3版,OpenGL封装类库

    Coin-3.1.3是该库的一个特定版本,它包含了对先前版本的改进和新功能。 Coin3D的核心概念是它对场景图(Scene Graph)的处理。场景图是一种数据结构,用于组织3D模型、相机、光源等元素,它们共同构成一个可视化的...

Global site tag (gtag.js) - Google Analytics