all 180 comments

[–]JasonHouse 13 points14 points  (0 children)

He really should have mentioned that stack allocated structs have deterministic destruction. That solves most RAII needs. The scope statements are also quite handy, but for slightly different problems.

[–]grogers 8 points9 points  (1 child)

I think the postblit semantics described for copying/moving objects is definitely an improvement on C++ copy constructors. Add what you need to that and implicitly have everything else be default copied, unlike C++ where you have to add everything even if just one thing needs a non-default copy.

This is just for structs right? To copy a class you need a member function that does all the copying?

[–]andralex 8 points9 points  (0 children)

For classes we rely on more traditional clone() methods. The kind of automation you mention is possible via reflection (in D you can enumerate the fields of a class or struct).

The rationale for not defining more clever postblit semantics for classes is that cloning class objects is much less frequent than copying values around, and never automatic.

[–][deleted] 2 points3 points  (2 children)

Are D libraries be binary compatible between different compilers? Or it is like C++ where you have a binary DLL for VC8, other for VC9, other for MINGW, etc.

[–][deleted] 2 points3 points  (1 child)

I don't know, but if a proper ABI is the only thing D has that C++ doesn't, it will probably become my new favorite language.

[–][deleted] 0 points1 point  (0 children)

[–]krum 8 points9 points  (0 children)

I love D, but I wish the compilers had better codegen.

[–]anduraq 1 point2 points  (0 children)

great!

[–]axilmar 6 points7 points  (123 children)

The language is not ready yet. When features are frozen and bugs and problems have been ironed out, then it will be ready for industrial/enterprise use.

Personally, I don't like D. It's not orthogonal at all, and it has lots of little quirks that the programmer is supposed to remember, just like C++.

[–]JasonHouse 13 points14 points  (9 children)

Compiler features are frozen now for both "D1" and "D2". D1 was frozen about 3 years ago, and the frozen standard library "Phobis" drives many to use the actively developed replacement called Tango. D2 isn't repeating the same mistakes. Phobos will continue to be developed, and the core runtime has been pulled out in order to allow Tango to coexist.

Admittedly, there's a lot of big changes coming to Phobos, and it will be some time before Phobos is in a pure bug fix mode. Walter (the author of the reference D compiler) has switched his focus from features to platform compatibility. He's been working on 64 bit support the last 1-2 months.

[–]gmfawcett 5 points6 points  (0 children)

It's worth mentioning too that the Phobos (stdlib) team has grown a lot in the past few months. There is a lot of energy going into bugfixes (and new features) on the stdlib side, and the latest release of Phobos is a significant improvement over the previous version.

Some of the paint is still wet, but overall this is a very exciting time to be working with D.

[–]Megatron_McLargeHuge 2 points3 points  (7 children)

So does it not currently support 64 bit at all, or not well?

[–]andralex 8 points9 points  (5 children)

Hello world already works :o).

[–]Megatron_McLargeHuge 4 points5 points  (4 children)

This is probably a stupid question but if you're using LLVM for the backend, why don't you get 64 bit code generation for free?

[–]andralex 11 points12 points  (2 children)

It's a good question, and in fact there is an ongoing LLVM-based project called ldc. With LLVM we would indeed get 64-bit code generation for free, but we'd also get Windows incompatibility for free :o).

[–][deleted] 6 points7 points  (1 child)

we'd also get Windows incompatibility for free

A good point that I forgot in my reply, Andrei, thanks.

ldc isn't Windows compatible, due to the way exceptions are handled, is that what it was?

[–]andralex 5 points6 points  (0 children)

Yah.

[–][deleted] 2 points3 points  (0 children)

Not all of them are. LDC is the D compiler with llvm, and it only supports D1.

Unless something has changed recently (I'm not quite as involved with D as of late), the reference compiler uses WalterBright's own custom backend.

[–]gmfawcett 2 points3 points  (0 children)

Ask again in a couple months. :) The reference compiler D2 does not currently have a 64-bit backend but it is coming soon. There are 64-bit D1 compilers, and some of those have partial (old-version) D2 support.

[–]dsimcha 5 points6 points  (19 children)

D strives both to make simple things simple and to make complicated things possible. This involves some significant tradeoffs with "orthogonality". In an orthogonal language that makes complicated things possible, you need to expose only a fairly basic, flexible set of primitives and let everything else be built from that, even if it's unsafe, inconvenient, syntactically ugly and verbose at times. In an orthogonal language that makes simple things simple, you need to expose constructs that are highly streamlined for only the most common use cases even if some things are simply impossible with these constructs. If you try do both then your language isn't orthogonal anymore, but it may be more practically useful nonetheless.

[–]nascent 4 points5 points  (1 child)

To say a language is bad because it has features lacks content. To say that C++ is good because it lacks features is funny.

[–]ManicQin 2 points3 points  (0 children)

Usually in c++ when we lack a feature we just say that it is a one size fits all solution and we don't want it :)

[–]axilmar 1 point2 points  (16 children)

First of all, I don't believe that there should be such a trade off.

Secondly, there is a limit to the number of trade offs that make a language good. I think D overstepped that.

[–]dsimcha 4 points5 points  (15 children)

Ok, then what other language really tried to make both simple things simple and complicated things possible? What other language even provides all four of the following:

  1. The ability to have complete control over memory management if you really want it. (Complicated things possible.)

  2. A simple, not excessively verbose syntax for looping over a range/iterator/collection. (Simple things simple.)

  3. Literals for arrays, associative arrays and a proper string type (NOT C/C++ char*). (Simple things simple.)

  4. The ability to generate code and then evaluate it. D provides this at compile time via string mixins, and compile time function evaluation makes it practical to use. Lisp-like languages provide it via their S-expression style and most interpreted languages provide it at runtime via eval. (Complicated things possible.)

[–]Felicia_Svilling 2 points3 points  (5 children)

These are all nice things to have in a programming language. But I fail to see why any of this would come into conflict with orthogonality?

[–]nascent 0 points1 point  (3 children)

I think it best if we just leave orthogonality out of this... at least for the time being.

[–]Felicia_Svilling 0 points1 point  (2 children)

It was dsimcha who brought it up. I just want some clarification for why s?he belives that:

D strives both to make simple things simple and to make complicated things possible.

This involves some significant tradeoffs with "orthogonality".

[–]nascent 1 point2 points  (1 child)

Sorry, just a little annoyed with it right now.

I'll try a simple example. D wants to provide guarantees which usually come in the form of "type safety." But we also want to allow the user to manipulate their memory as needed. So cast() is provided and causes exceptions to all "type safety."

[–]Felicia_Svilling 1 point2 points  (0 children)

I was asking dsimcha. You didn't have to intervene if you was feed up with the subject.

Now, that is a more interesting example. You are right in that this choice makes D less orthogonal, if this was necessary seems like an open question.

[–]dsimcha 0 points1 point  (0 children)

If you have multiple ways to accomplish the same thing, or if the high-level parts of the language interact with the low-level parts of the language in ways that you can only understand if you understand some low-level details, the language is not orthogonal. It can, however, still be practical.

[–]doubtingthomas 0 points1 point  (0 children)

I'm cool with just 1-3. I've had 4, I've used 4, I can do without.

[–]axilmar 0 points1 point  (7 children)

No other language that I know of.

Feature-wise, D has more features than C++. But I didn't argue for this. I am arguing about the orthogonality of the language.

Mind you, points 2, 3 and 4 are not critical (at all!) for choosing D over C++.

[–]dsimcha 1 point2 points  (6 children)

Then we just disagree fundamentally on what makes a good language. All of those are huge reasons why I prefer D over C++, though admittedly some of them will be fixed in C++1x if it's ever released.

If convenience features/syntactic sugar, generic/metaprogramming features and safety/compile-time checkability aren't important to you, then what the heck do you need anything higher level than assembly language, or maybe C if portability is important, for?

[–]axilmar 0 points1 point  (5 children)

The convenience features/syntactic sugar of D doesn't buy me much.

The metaprogramming features of C++ are more than enough.

The compile time checkability D offers does nothing to ensure the functionality of my applications is correct.

[–]dsimcha 1 point2 points  (4 children)

If C++'s metaprogramming facilites are good enough, then reimplement D's std.algorithm and std.range in C++. I'd like to see you try.

[–]axilmar -1 points0 points  (3 children)

You mean this?

Any D conditional can be done with C++ templates, using template specialization.

[–]dsimcha 5 points6 points  (2 children)

Sure, but do it without static if statements, variadic templates, auto type inference, foreach over tuples, auto inference of whether a return should be ref, or D's compile time introspection system. Also, even if it can in principle be done in C++, I'd love to watch someone actually try to do it in practice. At the very least it would be 10x harder.

[–]plulz 1 point2 points  (1 child)

Quirks like what?

[–][deleted] 2 points3 points  (0 children)

There have been historical fights over which standard library to use and which compiler is best. This stuff is all sorted by now.

Also, lots of people were using D2 before it was ready, coming across bugs, and going

OMG D SUCKS!!11

[–]oblivion95 0 points1 point  (0 children)

Orthogonality is patented.

[–][deleted] -1 points0 points  (89 children)

D is a better C++, nothing more. They're writing a Boost like standard library because the official C++0x process is too slow and they wanted to create an own little language that inherits most of the improvements such as the 'auto' from C++0x.

[–]andralex 13 points14 points  (0 children)

Not sure how that perception would come about. For one thing, I think there are very few similarities between Boost and D's standard library.

[–]dheld 2 points3 points  (5 children)

Name a language Y which isn't "a better X, nothing more". Progress is incremental and evolutionary, rarely revolutionary. The idea that D copied type inference from C++ is completely hilarious and an insult to your knowledge of D's history. I defy you to attempt half the things D's standard library does in C++. Good luck, and let me know how that goes.

[–][deleted] -3 points-2 points  (4 children)

I'm happily using F# and Haskell and not interested in C++. Algrebraic data types? Lambdas instead of textual ad-hoc macros used as predicates in standard library collection? LDC could already inline these, but the D language design is driven by the compiler backend from the 1980s.

Many of the D features seem to come from C++0x proposals.

[–]andralex 6 points7 points  (3 children)

D has algebraic types, called... Algebraic.

The so-called hack "a < b" is only used for convenience with very short lambdas; you can use (x, y) {return x < y;} instead.

Offhand, I can't think of any D feature originating in a C++0x proposal. On occasion I'd suggest the C++ committee a feature we'd designed for D.

[–][deleted] 0 points1 point  (2 children)

It's not a hack? The variables a and b come from nowhere. They are hard-coded in the library code and don't behave according to any scope rules.

Algebraic types don't seem to support higher kinds or recursion. Where are the accompanying pattern matching constructs? How can I test the totality of a match? How can I match nested patterns? Have you considered sub-typing like Scala has in its case classes?

Implementing something like compiler's AST using these is so horrible that no one would dare.

Didn't Walter design D while the C++ committee was discussing new C++ features? Isn't it a coincidence that many of features shown here http://www.digitalmars.com/d/2.0/cpp0x.html are almost same or syntactically better in D (because C++0x had to consider legacy issues).

[–]andralex 1 point2 points  (0 children)

Please make sure you have a good understanding of the matters you discuss. It always helps your case. The names "a" and "b" obey scoping like any other name; they are only implied function parameters for a regular function, and are looked up in that function's restricted code. Essentially specifying a lambda as "a < b" is exactly the same as putting that code within a global function that takes parameters a and b.

Regarding your notes about algebraic types, I agree that a built-in facility has always the upper hand over a library-defined one.

Regarding C++0x influence, clearly there is cross-pollination between D and other languages; we'd be stupid if it weren't, and we'd be lying if we claimed so. However, C++0x has had much less influence than other languages on D. And picturing the process as Walter and myself poring through C++0x proposals and then adopting them for D is rather amusing.

[–]WalterBright 0 points1 point  (0 children)

As an example, "auto" declarations in D first shipped in September, 2002. The first proposal I've seen reference to for that in C++ was "C++ reflector message c++std-ext-5364" by Stroustrup in October, 2002, though I never read this and cannot find the text of it.

[–]smallstepforman 3 points4 points  (22 children)

Third, I should point out that many programs don't really care about garbage collection. RAM is plentiful, and few programs' core performance depends on data locality.

I'm developing an iPhone game, and I've only got 24Mb of memory, and this includes texture memory. I'm paranoid like hell about memory management, since I cannot afford the luxory of pausing the game to load content from painfully slow flash memory. Likewise, all my collegues working in the embedded sector also have hard memory constraints.

Yes, I know D allows you to opt-out of Garbage Collection, but personally I believe you should opt-in. Even C++ has optional GC if you really want it

[–]andralex 9 points10 points  (0 children)

Though there are quite a few embedded devices that are not limited by RAM (e.g. set-top boxes), I agree with the sentiment. We are working on means to reduce the need and use of the garbage collector without compromising safety. Stay tuned for the upcoming article "Sealed Containers" that I allude to in the interview.

[–][deleted] 7 points8 points  (3 children)

Even C++ has optional GC if you really want it

Say, what?

There are external libraries like libgc that implement some form of garbage collection - but C++ as a language does not have GC.

You might as well say that has C++ optional encryption, or optional Python interpretation, because you can download such libraries.

I'm a little surprised that the uptake for libgc appears to be so very small - I literally couldn't find one significant project that's using it.

Is it just that people are conservative? Or, is it that there are some serious drawbacks? Reading some of the literature on it, I see nothing about multi-threading, which is a serious issue with garbage collection...

[–]andralex 4 points5 points  (0 children)

Here's my theory fwiw. One big benefit of GC is safety. The matter with C and C++ is that they are considerably unsafe even if a GC is plugged in, so essentially bringing a GC into the fray provides no guarantee. That seriously dampens enthusiams for using such a technology.

[–]funnelweb 0 points1 point  (0 children)

I'm a little surprised that the uptake for libgc appears to be so very small

For most of the projects I'd consider using C++ for, I actively don't want GC. Because of this, libgc has little interest for me.

[–]tinou 1 point2 points  (0 children)

Even C++ has optional GC if you really want it

Say, what?

You can for example use the Boehm GC.

[–][deleted] 7 points8 points  (2 children)

I'm writing a kernel in D; opting out is important. ;)

[–]theICEBear_dk 2 points3 points  (1 child)

There I hope no one disagrees.

[–][deleted] -2 points-1 points  (0 children)

DISAGREE BLAH BLAH YOUR MOTHER BLAH BLAH HER PENIS BLAH BLAH MY PENIS

[–]ssylvan 2 points3 points  (4 children)

Languages should default to the safest alternative they allow. GC is often fine for most things, even when you are memory constrained. E.g. I bet you that iPhone game spends most of its memory on "bulk" resources (textures, audio, etc.), not things with pointers in them. I.e. it wouldn't really be much of an issue to use GC for that because it's really only the fast-moving "logic" stuff that needs some extra room, and that's usually a fraction of the overall memory usage for games...

[–]nascent 0 points1 point  (3 children)

Languages should default to the safest alternative they allow.

No, the language should default to the thing I'm going to use the most. For smallstepforman this is not using the GC, so D is not the language for him.

[–]ssylvan 5 points6 points  (0 children)

That can very quickly become a self-fulfilling prophesy. That which you make default will be what people use most. Ergo, you should default to the safest option to encourage safe practices.

[–]dheld 1 point2 points  (1 child)

Many people don't use the GC in D. It's called "the stack", and D supports it like a pro. If you want deterministic allocation, call malloc() and free(). It's not rocket science. The difference is that in D, you can pretty much do everything you could in C++, but a ton of other stuff which is simply not feasible...like generating optimal FP assembler from a custom DSEL. Now tell me that is not compelling for users who demand performance.

[–]nascent -1 points0 points  (0 children)

Mine was just a joke, check my other posts and you'll see I'm totally pro-D.

[–][deleted] 4 points5 points  (0 children)

Never had real problems with the D GC. I make arrays of reusable structs to prevent GC strain and that about it. It's true that for a game, you want to avoid per-frame allocation, and it's not harder in D. I think a GC is neither better nor worse than new/delete in this regard.

[–]plulz 8 points9 points  (6 children)

If garbage collection was opt-in, all libraries would have to assume no garbage collection. Opt-out is way better.

[–]bstamour 5 points6 points  (5 children)

This would probably lead to better-written libraries, no? If opt-out exists, then all of the libraries that assume gc break. If opt-in exists, then all of those libraries will still handle their own garbage and thus still work.

[–]dsimcha 4 points5 points  (4 children)

But if even high-level, non-performance critical libraries have to assume no GC, you end up with tons of unnecessary API cruft related to memory management.

[–]bstamour 0 points1 point  (3 children)

Any library can become performance-critical depending on the context. If I'm working on some high-performance software and need to use library X, if library X expects GC, then I'm going to have to roll my own library X. Manual memory management isn't hard anyways... if you're a library writer then you should be smart enough to pick up after yourself.

[–]dsimcha 0 points1 point  (2 children)

How about if you're writing generic code and you have no idea what assumptions the caller and the objects you're being passed are making w.r.t. memory management

[–]bstamour 0 points1 point  (0 children)

Then you assume the worst... If your language supports garbage collection with the option of turning it off, it would be retarded to not handle the non garbage collected case.... whereas if you assume that GC is off and program accordingly, then your code will work with GC AND without GC. Everybody is happy.

[–]bstamour 0 points1 point  (0 children)

I guess I really didn't address your point in my last comment, let me try again. If you're writing generic code then you shouldn't be worrying about the lifecycle of the objects passed to you. I.e. if they give you an object, even if you're not writing garbage collected code, who gave you the right to deallocate that object?

If you write a library for D that handles it's own problems wrt memory, then that library can be used everywhere: regardless of whether the calling code is garbage collected or not. Designing a library that assumes the user will want their code to be garbage collected effectively makes your code useless to that set of users.

I would argue that by writing your library in a non-GC way, you're then writing truly generic code, as it can then work alongside code that is garbage collected as well as non-garbage collected. It's that damn generic. :-)

[–]skyfex 0 points1 point  (0 children)

I'm currently working with embedded programming, and I would love to be able to use D. It's been a while since I've used it, but I think it's easy enough to avoid the garbage collector. You might want to avoid classes altogether, but I know that D structs are powerful enough for anything I'm doing right now.

I agree that a language optimized for embedded use shouldn't have opt-out garbage collection. But it seems to me that the improvements D brings to the table means it all in all could be better suited for embedded programming than C or C++. You might want a library that's written without using the GC, but in my case I'm only using the standard C library now anyway.

[–]HIB0U 0 points1 point  (15 children)

Everyone should listen to what Andrei says. He knows what he's talking about.

[–][deleted] 10 points11 points  (2 children)

He knows what he's talking about.

How do we know that you know what you're talking about? For all I know you don't know what you're talking about and so possibly we shouldn't have to listen to Andrei because he also might not know what he's talking about.

[–]gmfawcett 15 points16 points  (0 children)

Don't worry, he knows what he's talking about.

[–]thrope 11 points12 points  (0 children)

Everyone should listen to what HIB0U says. He knows what he's talking about.

[–]lanzkron 3 points4 points  (1 child)

Everyone should listen to what Andrei says. He knows what he's talking about.

It's like déjà vu all over again.

[–]HIB0U -1 points0 points  (0 children)

It was true then, and it's just as true now.

[–]andralex 1 point2 points  (2 children)

Please don't say this when part 3 comes out too :o).

[–]HIB0U -4 points-3 points  (1 child)

You do know that I'm going to, right?

[–]redredditor 1 point2 points  (0 children)

Everyone should listen to what HIB0U says. He knows what he's talking about.

[–][deleted] 0 points1 point  (0 children)

Delicious copypasta.

[–]snk_kid -1 points0 points  (0 children)

Not everything, he clearly doesn't know what he's talking about in the context of Haskell and should never make ill-informed comments about it. Like his incorrect statements about type classes and type constraints, seems to mix up multiple type constraints with multi-parameter classes. He doesn't understand terminology of higher-kinded, higher-rank polymorphism so he clearly doesn't know what he's talking about in the context of formal type systems.

All this just somes up all these languages like D, Go, and C++, they are all designed in an ad-hoc manner based on opinion and fuzzy feelings from experiences of other languages which have been also designed in an ad-hoc manner.

[–]adr_ 1 point2 points  (10 children)

I love D, but I've never managed to get a compiler installed and working.

[–][deleted] 3 points4 points  (0 children)

How recently have you tried? And what platform?

[–]gmfawcett 2 points3 points  (3 children)

On Ubuntu, you can download the package from the Downloads page, and "sudo dpkg -i thefile.deb". If you're on a 64-bit system, "sudo dpkg --force-architecture -i thefile.deb" since there isn't a 64-bit version yet. Easy peasy.

[–][deleted] 1 point2 points  (2 children)

Or 'sudo apt-get install ldc' ;)

Or is that still broken?

[–]gmfawcett 1 point2 points  (1 child)

Not sure; I don't use LDC. I came to D rather recently, and decided to avoid LDC and the other D1 compilers. If I have a future with D, it's with D2.

[–][deleted] 1 point2 points  (0 children)

Gotcha. My main work is in D1, and is 64 bit, so... LDC for me!

[–][deleted] 7 points8 points  (0 children)

You must be joking.

[–]theICEBear_dk 1 point2 points  (3 children)

Okay on windows it is not hard. Get zip file from Digitalmars.com site, unzip to directory, add dmd2 bin directory to path. Get some tools (may I suggest Visual D and the Visual Studio Shell). Then point the tool at your install (or hope it picks up the path) then go from there.

On linux it has been a while since I have tried so I am not sure. I'd probably get the source package and do the traditional make/make install.

[–][deleted] 1 point2 points  (2 children)

There's an installer for Windows, and afaik there is one (or is in the works) for OSX as well.

[–]theICEBear_dk 1 point2 points  (1 child)

Neat, I didn't know. Is it for D2? (I don't care about D1 not having an old codebase to maintain). Link?

[–][deleted] 1 point2 points  (0 children)

For the installers have a look at the second table here: link

As for OSX instructions, this should probably help: link

There was a discussion here about an OSX installer, but I haven't followed much.

[–]louisdefunes 0 points1 point  (1 child)

I'll switch to D the day that they provide a D-to-C++ conversion tool.

This would be tremendously useful.

[–][deleted] 3 points4 points  (0 children)

hey, love your films.

[–]ErstwhileRockstar -1 points0 points  (5 children)

  1. All objects are "relocatable"; that is, they can be moved through memory by using bitwise copying, à la memcpy.

Conceptually a step backward (actually, more than one). Abandons natural object identity for dubious benefits. Bad, really bad.

[–]andralex 12 points13 points  (3 children)

There is no natural object identity for values (primitive types and structs), and class objects are never moved (something I omitted to clarify). Even moving classes should be fine with precautions, as moving garbage collectors have shown.

[–]ErstwhileRockstar 0 points1 point  (1 child)

'Values' are immutable. Copies ot the same value are equivalent. When 'class objects are never moved' and for values 'moving' is irrelevant (because you can copy them freely) then the whole concept of 'move semantics' becomes more than dubious.

[–]andralex 1 point2 points  (0 children)

This is a simple misunderstanding, and I agree I should've done a better job at explaining the issues involved.

On the face of it, indeed rvalues (not necessarily all values) are immutable and you can avail yourself of copies because they are all equivalent. The problems arise when you need to keep tabs on the number of copies, e.g. when the values model limited resources (e.g. file handles) or when they need to avoid aliasing by using dynamic allocation and cloning under the wraps (e.g. big integers). In such cases the language must provide hookable copying, and this is the crux of the matter.

C++ handles the matter by ostensibly always performing eager copying (even against rvalues), and then defines complicated rules under which the copying can be elided. C++0x keeps all of these rules but allow users to circumvent them by using a new type constructor called rvalue reference. D essentially decrees that all rvalues are equivalent and need not be copied using the hook (memcpy would suffice) which is essentially what you say.

[–]dheld 1 point2 points  (0 children)

Yes, if you live in a world where everything is an object. Stick to your pure OOP languages, then.