Note that in your Java examples, you are checking, then casting anyway. The D version does both the check, and subsequent conditional cast, all at one go. Aesthetics, I suppose.
But you don't understand, I make no point about casts but about operations which instead of throwing return a bogus value when they fail. I don't know D, don't know if there are other such operations so I write about casts. As far as in-the-language operations go... Array bounds checking is enabled for debug builds (on all three array types), and throws an exception. Asserts throw -- although generally one shouldn't catch these except in unit tests where failure was the desired result. Running "out" of memory throws. (Attempting to access members of nulls gives an Access Violation currently. I admit that, in debug builds, a NullReferanceException/Error wouldn't be a bad idea.)
So the general rule of thumb seems to be: if you expect failure a notable portion of the time (about half or so is my personal choice, although its difficult to quantify) return a default or "failed" value; otherwise throw an exception, and be sure to document it.
"Casting often is a sign of a bad design." That is true, but often it is a sign of a language's bad design (think Java pre-1.5 collections) and you just have to cast. I'd rather not, if I can help it. But I do hear you. Luckily true/explicit casting is rarely neccessary in D. Given a D array that needs to become a pointer, there's a ".ptr" property which directly exposes the raw pointer. The usual implicit upcasts of the C/C++/Java/etc world are still there (short -> int, for example). And we do have a fairly nice templates system in place, one which is by-design suitable for meta-programming, rather than having to be "abused" for such practices as C++ templates often are. (I've seen some interesting things done with this, such as compile-time regexp engines, and a parser generator on a subset of BNF. I'm almost ashamed not to have made more use of it myself.)
In short I've not often seen this problem in D, but it might just be a result of personal style.
They aren't bad points, honestly. But just so you understand why I'm doing what I'm doing, and why I think the null result is a handy thing, here's a little more context. The following function is a member of the Database aggregate. It only differs from project code in that I stripped comments and a few minor operations to highlight the point.
The alternative would be to have two separate functions, one of which calls the other with an (implicit) upcast anyhow. While that wouldn't be, strictly speaking, a bad way to dit, it also adds 1) maintenance cost, 2) self hand holding, as the Database entity knows all about BObject entities anyhow, 3) the ever so slight overhead of an extra function call on the stack.
But do you really assert or guard your every cast? Then you're one of those heroes that can use C as well, after all you can check for every -1 that may be given to you instead of a valid value. My each and every single cast? No, I admit I don't -- but then I do try to avoid casts if there are significantly better ways to achieve what I want. (On the D forums there was a mantra during discussions of the cast syntax along the lines of, "Casting often is a sign of a bad design.")
The problem is, people don't do that, and other problem is, you often want to deal with the problem not where it happens but much earlier on your call stack Oh I do agree with that, which is why I use exceptions most of the time. But in this case, I have found in practice that the "cast(Class/Interface) object == null on failure" idiom actually works out well. Personal gnosis, perhaps.
Certainly, but its no problem to utilize contracts for that purpose. (Which i also do quite a bit.) Also, note that in the example I gave, if it failed, then it just skipped over the bit that relied on that implementation. And actually it is not neccessarily a sign of a design problem. There are perfectly good use cases -- for an example, in my Bovis project a given database object may, or may not, be a peer to a user connection. User objects are just exactly like any other object, except that expose a few additional things. For an example, User objects can "own" another object, where no other ones can. So an attempt to set the owner looks roughly like:
BObject obj =...; if (auto user = cast(BUserObject) obj) { // set ownership details } else { throw new BovisException("... "); }
So here we are. Did I end up throwing an exception in this case anyway? Sure did -- but I got to control what exception was thrown, making it easier to target this one. (I want to catch my own exceptions, and expected runtime exceptions, but everything else I want to slip through and crash.) If I really, really just wanted the cast succeed and cared for nothing else, that's what the assert contract is for.
auto foo = cast(Something) bar; assert(foo, "our bar is not a Something!?");
But what if I need feature X of some other GUI library? Or what if I don't need the majority of the standard GUI library? Or maybe I need a GUI which supports forms/markup based interfaces? Or, or, or... Its better to have options, and choose the best tool for the job. (Just like with programming languages!;))
That said, there are already some efforts under way. There are wrappers/bindings being written for existing libraries, such as DWT (SWT) and wxD (wxWindows). And there are written-in-D-for-D GUI libs such as DUIT, DFL, SDWF, and Harmonia.
Originally the language was to be called Mars... but the name just didn't stick. Anyhow, try googling for the full phrase "The D Programming Language" and you'll have better luck. That particular phrase is the "canonical sugar" to be included somewhere in all sites/pages/resources pertaining to D. (Not that it always happens, alas.)
I would hate to think I have to deal with exception handling scaffolds every time I want to check whether an object implementing interface IA also implements interface IB, or IC. I'd much rather just write:
IA a =...; //... if (auto b = cast(IB) a) { //... } //...
Than have to write:
IA a =...; //... try { auto b = cast(IB) a; //... } catch (Exception ex) { // do nothing, don't care } //...
And seeing as how trying to use any members of a null is going to throw stuff anyway... I don't see any problem with it. In fact, I've made quite free use of it in my D code. To each their own, I suppose.
Well, "dynamic" (variable-length) arrays, associative arrays (which are actually implemented as fast hash trees, in case anyone was curious), and slices account for a good deal of what STL has been used for. Being able to use strings as cases to a switch statement, while not strictly speaking a collections concept, also alleviates some use cases. A foreach statement, which is itself applicable to classes/structs (via the opApply overload).
I really don't know exactly what to point out without knowing exactly what features you need, though.:) Even things like stacks can be implemented as arrays in D (or very simple class/struct wrappers around an array if you need the security) rather simply.
Multiple Inheritance is an often abused feature which is also a source of difficulties when it starts to get deep. (And problems arising out of diamond inheritance, etc.) Granted, it has its moments of usefulness.
For those special moments, a D interface will usually suffice. And if you happen to know that a majority of implementations are going to be the same, you can define a standard implementation in the form of a mixin template. Convoluted example:
interface IWhatever { int foo (int); int bar (int); }
template StandardWhatever { int foo (int n) { return n * 2; } int bar (int n) { return foo(n) + 2; } }
class Typical : IWhatever { mixin StandardWhatever; }
class Special : IWhatever { int foo (int n) { return n * 3; } int bar (int n) { return foo(n) - 1; } }
Mixins have certain additional features in that 1) they are templates, and therefore can be generic and/or take template parameters, and 2) they can be named. An example of this is in the Signals/Slots module of the current standard library (Phobos).
import std.signals;
// class Foo is itself a signal with an int parameter class Foo { mixin Signal!(int); }
// class Bar contains two signals, one taking an int and the other a char[] class Bar { mixin Signal!(int) alpha; mixin Signal!(char[]) beta; }
Actually in D you can check for the existance of a method by name at compile-time. I admit I haven't used this particular feature myself as yet, so I may not be remembering just exactly how to do it, but it should be at least close.
static if (is(typeof(anObject.doSomething))) { anObject.doSomething; }
Using traits template meta-functions one can check that 'doSomething' has a certain return type, that it takes parameters of a certain number and with certain types, etc. Should you actually need that much. As for the interfaces technique above, this is also available in D if you need to guarantee a sleugh of properties. With both a compile time means:
static if (is(typeof(anObject) : MyInterface)) { anObject.doSomething; }
And a run time means:
if (auto faced = cast(MyInterface) anObject) { anObject.doSomething; }
Because D returns a null for a failed up/down-cast of objects, such an if statement effectively filters on inheritance of classes / implementation of interfaces.
Actually I recall someone starting a "Docoa" project quite some while back. Honestly don't know the status of the library as I haven't had a personal need for it, but Google might help locate it.
We (the D programmers) don't like #ifdef either... which is precisely why we have in-language alternatives for the cases where #ifdef and company were (at least potentially) useful. For example, say you have a function Bob. Bob is a very useful character... but he relies on some function in the local Operating System's API. Let's say on Windows Bob needs to use Wally, and on Linux he needs to use Larry. Okay... no problem.
void Bob (int a, int b) { version(Windows) { Wally(a, b); } else version(Linux) { Larry(b, a); } else { static assert(false, "Unsupported Operating System."); } }
As for is-expressions... suppose you have a template called... uhm, Ted. And Ted is, also, quite useful... but if Ted's parameter happens to be, say, a float, you want it to do something a little different. But! You don't want to have to write a second full version of Ted just to change that one little thing! No problem.
template Ted (T) { static if (is(T == float)) { // do stuff the floating way! } else { // do stuff the usual way. } }
You don't have to re-write all your old C code, as D is link-compatible with C. And adding these features to C/C++ has been tried... that's how D got started in the first place! (See the DMC compiler for what I'm talking about.)
First off, which came first, the language or the IDE? (Answer: language. I'm pretty sure no one had an IDE to write Assembly or COBOL in, back in the day.)
Secondly, here's a list of known Editors that may be used with D:
http://www.wikiservice.at/d/wiki.cgi?EditorSupport
I've been personally using EditPlus2 to write D source for a few years no with no issue. I haven't even missed auto-completion or tips. Building has also been straight-forward, thanks to the written in D for D make utility "Build" (now commonly referred to as "bud"). And of course, traditional make works as well, if you feel so inclined.
Something which may be of interest. Benjamin Shropshire recently posted on the D newsgroup with a parser generator he'd written using D template metaprogramming. The parser generator itself (one source file) can be viewed at http://www.webpages.uidaho.edu/~shro8822/dparse.d and a complete usage example at http://www.webpages.uidaho.edu/~shro8822/exp_gramm er.d.
But what if I need feature X of some other GUI library? Or what if I don't need the majority of the standard GUI library? Or maybe I need a GUI which supports forms/markup based interfaces? Or, or, or... Its better to have options, and choose the best tool for the job. (Just like with programming languages! ;))
That said, there are already some efforts under way. There are wrappers/bindings being written for existing libraries, such as DWT (SWT) and wxD (wxWindows). And there are written-in-D-for-D GUI libs such as DUIT, DFL, SDWF, and Harmonia.
Originally the language was to be called Mars... but the name just didn't stick. Anyhow, try googling for the full phrase "The D Programming Language" and you'll have better luck. That particular phrase is the "canonical sugar" to be included somewhere in all sites/pages/resources pertaining to D. (Not that it always happens, alas.)
Well, "dynamic" (variable-length) arrays, associative arrays (which are actually implemented as fast hash trees, in case anyone was curious), and slices account for a good deal of what STL has been used for. Being able to use strings as cases to a switch statement, while not strictly speaking a collections concept, also alleviates some use cases. A foreach statement, which is itself applicable to classes/structs (via the opApply overload). I really don't know exactly what to point out without knowing exactly what features you need, though. :) Even things like stacks can be implemented as arrays in D (or very simple class/struct wrappers around an array if you need the security) rather simply.
Actually I recall someone starting a "Docoa" project quite some while back. Honestly don't know the status of the library as I haven't had a personal need for it, but Google might help locate it.
You don't have to re-write all your old C code, as D is link-compatible with C. And adding these features to C/C++ has been tried... that's how D got started in the first place! (See the DMC compiler for what I'm talking about.)
First off, which came first, the language or the IDE? (Answer: language. I'm pretty sure no one had an IDE to write Assembly or COBOL in, back in the day.) Secondly, here's a list of known Editors that may be used with D: http://www.wikiservice.at/d/wiki.cgi?EditorSupport
I've been personally using EditPlus2 to write D source for a few years no with no issue. I haven't even missed auto-completion or tips. Building has also been straight-forward, thanks to the written in D for D make utility "Build" (now commonly referred to as "bud"). And of course, traditional make works as well, if you feel so inclined.