The D Programming Language, Version 1.0
penguinblotter writes in a journal article: "Soon, Walter Bright is scheduled to release version 1.0 of the D Programming Language. D is a systems programming language. Its focus is on combining the power and high performance of C and C++ with the programmer productivity of modern languages like Ruby and Python. Special attention is given to the needs of quality assurance, documentation, management, portability and reliability. D has appeared on Slashdot a few times before, and Walter has continued to add more and more features. Most Slashdot community comments in these articles have been offered on feature X or spec Y without reading through the extensive D newsgroup archives. It has been here over the past seven years where extremely gifted and experienced programmers hashed out discussions and arrived at excellent implementations of all the ideas discussed." Read on for the rest of penguinblotter's writeup.
For those with a C/C++ background, D offers:
From D's creator:
For me, it's hard to pinpoint any particular feature or two. It's the combination of features that makes the cake, not the sugar, flour or baking powder. So,
For those with a C/C++ background, D offers:
- native code speed
- extremely fast compilation times
- garbage collection (although you can manage your own memory if you want)
- OOP - by reference only, easy initialization, always virtual
- cleaner template metaprogramming syntax, more powerful templates, as well
- built-in dynamic and associative arrays, array slicing
- versioning (no preprocessor madness)
- link-compatibility with C
- nested functions
- class delegates / function pointers
- module system
- similar syntax
- No virtual machine or interpreter
- built-in unit testing and design-by-contract
From D's creator:
For me, it's hard to pinpoint any particular feature or two. It's the combination of features that makes the cake, not the sugar, flour or baking powder. So,
- My programs come together faster and have fewer bugs.
- Once written, the programs are easier to modify.
- I can do (1) and (2) without giving up performance.
...it's just another version race. D may have won for now, but someone out there is already working on the E programming language. ;-)
I'm looking at using it via GDC for my next project. For people who use C/C++ regularly, this is something you ought to look into.
It's not a toy language. If you're a C++ programmer, you'll be almost immediately functional in the language. And you can call C and C++ libraries seamlessly. It's pretty sweet.
"You can either have software quality or you can have pointer arithmetic, but you cannot have both at the same time."
From the compared to C/C++ list:
* native code speed
As opposed to C/C++.
* extremely fast compilation times
Point granted (compared with most C++ compilers).
* garbage collection (although you can manage your own memory if you want)
Point granted, even though C and C++ arguably have optional garbage collection as well (if you link to the right library).
* OOP - by reference only, easy initialization, always virtual
Only value semantic? Meyer had to accept that value semantic was useful, and add it to Eiffel eventually, and C# added it over Java.
And no way to specify that a function will always be the one specific. Good luck doing any kind of reasoning there.
Bragging about missing features, that are essential to many tasks.
* cleaner template metaprogramming syntax, more powerful templates, as well
*More* powerful templates? The usual complaint is that C++ templates are too powerful (a Turing-equivalent compile time language).
* built-in dynamic and associative arrays, array slicing
Not exactly a recommendation that the core language apparently is so weak that these can't be put into libraries.
* versioning (no preprocessor madness)
I'm guessing he meant variants here, the preprocessor is often used for variants, rarely for versioning.
* link-compatibility with C
Which C and C++ of course lacks?
* nested functions
Point.
* class delegates / function pointers
Obviously both C and C++ have function pointers.
* module system
More preprecessor replacement here.
The C#/Java list:
* similar syntax
But totally different from C++?
* No virtual machine or interpreter
You can compile Java and C# to native code as well, so this is just another case of bragging about a missing feature.
* built-in unit testing and design-by-contract
I'm a C++ programmer, and this is by far the most interesting aspect of the D language (and of Eiffel before that). Don't know why it should be in the Java/C# list.
I took it upon myself to learn D not more than a few weeks ago. A classmate introduced me to the language last spring.
While I'm still learning D, it has some notable features:
Of course one may argue that none of this is necessary and could be made independent of the language itself. My belief is that would increase the complexity of coding in D.
If you're interested in D you should visit http://www.dsource.org/. There are some interesting projects such as Derelict (collection of C game bindings) and Bud (make and SCons replacement).
This slashdot-related signature is a stub. You can help kihjin by expanding it.
After working so hard to get from C to C++, I don't see why I would settle for D. My next programming language is going to be B- or better.
Want to improve your Karma? Instead of "Post Anonymously", try the "Post Humously" option.
Java isn't that much slower if you actually take the time to compile it to native code first. Using something like a JIT compiler http://en.wikipedia.org/wiki/Just-in-time_compilat ion can greatly increase the speed of your code and put it close in line with C++.
This is a bit of an old myth. Almost all Java is run as native code these days, even on VMs, and is mostly pretty close to C++ speed. Benchmarks that show Java as significantly slower than C++ usually result from not allowing the VM enough time to perform native code translation of time-critical code. Java has moved away from JIT compilation (as against the later optimisation of HotSpot) because it led to long start-up times - you had to wait for code to be compiled to native before it ran. Now Java usually starts up as interpreted, with the translation to native code happening later on, in the background.
Where C, C++ and D win out over Java in terms of performance is when you need programs that have to start up fast, run fast, but only for short periods (a few seconds).
I'm sure D is a lovely language, but it just seems like another incremental change over C++, like Java and C# before it, and like both of those languages what it's lost and the opportunities it misses are as telling as the little tweaks it makes to improve things.
No-one has yet been successful, IMHO, in developing a really good industrial programming language. Those that make it tend to be pragmatic, practical tools like C and Perl and FORTRAN and COBOL. To be sure, each of these has many widely-acknowledged weaknesses, but the overall balance between those weaknesses and what you could get done using the language was right.
I can increasingly see why some well-known programming language designers shy away from feature comparison ticklists. I think it's because as soon as you go down this route, you bias the comparison so much that it's meaningless. For example, consider the first checklist cited in the Slashdot write-up. (I note in passing that this is a wiki, and may change before you read this.) Here are some of the "yes or no" (almost) categories:
Templates or executable macros No difference in expressive power is acknowledged between LISP macros and C++ templates. Thread synchronization primitives With no reference to how expressive they are, and how powerful the idioms supported by them? This one is really telling, IMHO, because I don't believe the future lies in classical thread sync and locking primitives. The whole approach is just too prone to deadlocks and race conditions to withstand the heavily parallel future that multicore chips are starting to bring into the mainstream. When you have ideas like pure function programming languages, operating in a world without side-effects where explicit locking isn't necessary, or interesting ideas for inter-thread communication such as those in Erlang, another variation on built-in pthreads just isn't worth much. Enumeration So again, we acknowledge no difference between simple and low-level enumerations such as those in C, and concepts such as disjunctive types and pattern-matching that are very powerful, remarkably elegant, and mainstream in certain families of programming language. Again, this is just papering over a gap, where other languages operate on an entirely different level. Long double floating point (80bit) This is just desperation. Pretty much no-one uses 80-bit floating point arithmetic IME (and yes, I do work in the field). The portability hazards and lack of true support from almost every mainstream architecture make them almost irrelevant, except perhaps for a few very small niches. Lexical Closures Another telling omission: the power of all those neat functional programming features is dramatically reduced when you can't construct functions on-the-fly.On top of all of this, the feature lists invariably gloss over some less concrete things that are nevertheless very important to systems programming languages. How portable is D? How many production-quality implementations are available? Is the language standardised or under the control of a single, commercial body? How much backing is there behind the language in the commercial development space; do others write libraries specifically for this language, or is it reduced to using C-style interfaces at the lowest levels anyway, and what impact does this have on the usefulness of features like DBC, exceptions, and so on? Does the language have an active hobbyist/volunteer community supporting it?
I could go on, but I don't want this post to disappear into the oblivion any more than it already will. Although I'm deliberately focussing on criticising in this post, as I often do with D, I keep an open mind and will happily engage in debate with others, or even be proved wrong by people who have found D to have compelling advantages. So go ahead, D advocates, start your counter-arguments here...
If you disagree, post your argument. (-1, Overrated) isn't your personal censorship tool for views you don't like.
LOAD "SIG",8,1
The same way as countless other programming languages have in the past, I imagine. Why do you think garbage collection requires running your code under a VM?
Of course, you're overlooking all the overhead of monitoring the code long enough to determine which on-the-fly optimisations are worth performing, and of compiling the code itself, neither of which is trivial.
True, though of course it's not without overheads. Almost all of the Big Claims(TM) made by GC advocates in these discussions come with a catch: state-of-the-art GC method number 17 has a lower amortised cost of memory recovery than explicitly freeing it C-style!*
* But only if your system contains 10x as much memory as the program will ever need anyway.
This is traditionally followed by a wisecrack about how memory is cheap, followed by three enlightened posters pointing out the stupidity of that argument for multiple reasons. :-)
That depends a lot on context. If you really have a system where the overheads of GC are trivial but all the advantages are present, it seems a fair claim. It's just not likely to be universally true, and representing it as such would indeed be disingenuous.
If you disagree, post your argument. (-1, Overrated) isn't your personal censorship tool for views you don't like.
My feeling is that languages shouldn't try to satisfy all possible needs. Rather, we should have small and clean languages, use the right tool for each job, and combine code libraries from different languages when needed. (I regularly use 3-6 languages in a single project and my life is much happier for it.)
(Legacy support is critically important too, but it is vastly better to provide legacy support by providing ways to call older languages, especially the lingua franca of C, rather than demanding that the new language be a superset of the old. I still call numerical libraries written in pre-1970 Fortran, but that doesn't mean I have to write my code in a Fortran derivative.)
If a thing is not diminished by being shared, it is not rightly owned if it is only owned & not shared. S. Augustine
One area I see D being useful in is integration with Python. Writing to the raw Python/C API is cumbersome. (Managing reference counts is tedious.) Boost.Python is difficult to build and slow to compile. I've written a library for D called Pyd, whose purpose is not entirely unlike Boost.Python's.
Pyd is easy to use. It provides its own extension to Python's distutils. Usually, you just need to make sure the D compiler is on your PATH, write a setup.py file, and run python setup.py build.
"Hello world" in Pyd looks something like this (and I apologize for the lack of indentation):
The Squeak runtime for Smalltalk is written in Smalltalk. There is a smallish subset of Smalltalk used to write the basic functionality, which is compiled to native code. This then supports the whole language. The same model is, I believe, used for JNode, an operating system written in Java...
I am TheRaven on Soylent News
Wait...C++ without the bullshit? That takes away all of C++!
Haec merda tauri est. Ceterum censeo Carthaginem esse delendam.
I noticed that a comparison to Objective-C is quite conspicuously absent from the list of languages compared to D. Why is it missing? Granted D seems to be a much greater change to C than Objective-C is but I can't help but thinking that one of the main attractions to D seems to be its heap-based garbage-collected object system. You can already get the object runtime with Objective-C. If you use GNU you can even have Boehm GC (which is apparently the GC that D uses). If you use Apple you will have to wait for Leopard to get GC. Another new Objective-C feature is the ability to use full C++ objects as instance variables in your Objective-C classes and do the right thing with initializing (calling the default no-argument constructor upon alloc).
On top of that, Objective-C actually includes tons of reflection information. Although Objective-C has protocols which are roughly equivalent to Java/C# interfaces they are almost completely unnecessary. In Objective-C one can query at runtime whether a method is implemented or not and if so call it. So whereas in Java you'd do this:
in Objective-C you can do this:
The difference being that in the Java case you have to declare MyInterface as containing the one doSomething() method and inform java that your object extends MyInterface whereas in Objective-C you merely need to provide a doSomething method on your object.
Basically that means that in Objective-C every single method effectively becomes an interface. You would not believe how useful this is once you realize it. Note that at runtime there is ZERO difference. In both the Java and Objective-C cases the object is being checked to see if it implements something. Same with C++ if you use dynamic_cast<>()
Granted every language has its niche and I'm sure D will find its. Objective-C's niche is definitely GUI programming. The ample reflection information allows for easy implementations of archiving (serialization) and most importantly key-value coding and the related action methods pattern. It's a pretty damn cool thing when your RAD tool simply outputs archived objects that refer to methods to be called upon certain actions simply by name.
0XA1_2_C35_4_5_6_5P6_Li
Give up? Why, it's an imaginary real. Yes, you read that right. Oh, and I specified it in hexadecimal, just to prove I can. And I threw in some underscores because you're allowed to do that too. Have you guessed what an imaginary real is yet? This is supposed to be the "simpler C/C++ replacement."
A good language strives to find a few constructs that solve multiple problems. A bad language takes the kitchen sink approach. C and C++ are not good languages, but wide deployment and support make them useful anyways. D does not have that, but the designers do have the luxury of learning from the mistakes of the past. So what the hell is their excuse?
I wasn't happy about that either. Garbage collection in a language with destructors leads to wierd semantics, which is why Microsoft's "Managed C++" is a nightmare. I corresponded a bit with Walter Bright in the early days of D, but didn't press the issue.
What seems to work in practice is reference counting. GC gets most of the academic attention, but Perl and Python are both basically reference counted, and the result seems to be that programmers in those languages can ignore memory allocation. Java programmers have to pay a bit more attention, worrying about when GC will run and when finalizers will be called. Reference counting is deterministic; the same thing will happen every time, so timing is repeatable. That's not true of GC.
There are two basic problems with reference counts - overhead and cycles. Overhead can be dealt with by hoisting reference count updates out of loops at compile time, so that you're not frantically updating reference counts within an inner loop. Hoisting (along with common subexpression elimination), by the way, is also the answer to subscript checking overhead.
Cycles are a more serious problem. Conceptually, the answer is strong and weak pointers (in the Perl sense, not the Java sense), which allows the programmer to express things like trees. (Links towards the leaves should be strong pointers; back pointers towards the head should be weak pointers.)
In practice, cycles aren't a serious problem, because they're generated by design errors and tend to happen in normal program operation, so they show up early in testing as memory leaks. Dangling pointers, on the other hand, tend to show up in error cases, which is why they survive testing to become delivered bugs.
Ideally, you'd like to detect cycles at the moment they're created, at least for debug purposes. This is quite possible, although there's substantial overhead.
Attempts to retrofit reference counting to C++ via templates have been made, but they are never airtight. To get anything done, raw pointers have to leak out, which makes the reference counting scheme very brittle.
While D strings are mostly implemented as character arrays, it works quite differently than C. Here are some notable differences:
- D arrays are bounds checked. No accidental buffer overflows here.
- D arrays are dynamic, you can resize them and concatenate them together.
- D strings are D arrays, so they get the above bonuses.
- D has distinct 'char', 'byte', and 'ubyte' types. char[] != ubyte[]. When you use foreach to iterate over a char[]/string, it will expand each codepoint (or whatever they are called) to a dchar (which is a 32 bit character) for you. ubyte and byte are used for plain-old-data, instead of the unfortunate C char.
- Garbage collection frees you from worrying about where the strings go. No accidental memory leaks here.
There is also a nice alternative to the plain old strings called dstring, which gives you even more benefits of d's arrays like indexing and slicing (you can safely leave foreach alone with it). http://www.dprogramming.com/dstring.php
I've used both D strings and C strings, and D's strings just felt so much better.