My thoughts & experiences with D so far, as a novice D coder

deadalnix deadalnix at gmail.com
Wed Mar 27 09:04:49 PDT 2013


On Wednesday, 27 March 2013 at 15:34:20 UTC, Vidar Wahlberg wrote:
> I know I'm probably going to upset some people with this, 
> bashing their favourite child and all, but I wanted to let you 
> know the experience I've had with D so far, as a novice D coder 
> with a heavy Java & light C++ background.
> It's not that I dislike D, in fact there are tons of things I 
> love about it, it's pretty much exactly what I'm looking for in 
> a programming language at the moment. Yet, I encounter some 
> frustrating issues when coding, often leaving me with the 
> impression that I'm fighting the language more than the problem 
> I'm trying to solve.
> True, there are many things I don't know about D, compilers or 
> the inner workings of a computer, and some of the fights I have 
> with the language are likely started by myself because I'm 
> dragging along my bias from other languages, drawing 
> misconceptions on how the D language actually works.
> My intentions are not to insult, but shed some light on some of 
> the difficulties I've faced (and how I solved them), with the 
> hope that it will help others from facing the same difficulties.
>

That is fine don't worry. Knowing what people have trouble with 
when starting with D is very valuable IMO.

> Woes:
> -----
> - I find myself in a world of pain when I want to share data 
> more complex than the basic data types (int, char, byte, etc) 
> across threads. Seemingly the magic trick is to "cast(shared) 
> foo" (or "cast(immutable)") when passing objects/references to 
> another thread, then "cast(Foo)" back on the receiving end (as 
> most classes/structs in the standard library refuse to let you 
> call any methods when the object is shared). The examples in 
> the source and TDPL are fairly limited on the issue, it mostly 
> covers only those basic data types.
>

Well, that is a long standing issue. shared is poorly defined and 
inconsistently implemented. Sad, but true.

> - While the "auto"-keyword often is great, it can lead to 
> difficulties, especially when used as the return type of a 
> function, such as "auto foo() { return bar; }". Sometimes you 
> may wish to store the result of a function/method call as a 
> global variable/class member, but when the function/method 
> returns "auto" it's not apparent what the data type may be. 
> While you may be able to find out what "bar" is by digging in 
> the source code, it can still be difficult to find. One example 
> is to save the result of "std.regex.match()" as a member in a 
> class. For me the solution was to "import std.traits", create a 
> function "auto matchText(string text) { return match(text, 
> myRegex); }" and define the class member as 
> "ReturnType!matchText matchResult;" (do also note that function 
> & member must come in the right order for this to compile). 
> This was all but obvious to a novice D coder as myself, the 
> solution was suggested to me in the IRC channel.
>

Yes, I have to say that it is a pain sometime. Additionally, it 
have some rough edges you may want to know :
  - Function that never return are inferred void. I would have 
preferred typeof(null) as void lead to many static and repetitive 
code for nothing when doing metaprograming.
  - Type inference handle very poorly recursion. It should simply 
exclude the recursion when doing type inference as it won't 
change the return type. The error message can be very opaque.
  - In some cases, you have to add explicit casts when implicit 
would have been enough in theory (but the type inference 
mechanism is confused).

Back to your issue, you may want to use typeof . Sometime, it is 
plain better as type can become complex when doing 
metaprogramming (and phobos is full of this). You can also use an 
alias in order to make things look nice.

alias FooT = typeof(foo());
FooT bar;

bar = foo(); // Happy ?

>
> Gotchas:
> --------
> - The lack of "rectangular" arrays created at runtime in D 
> ("int i = 5; int[i][i] foo;") can be quite confusing for 
> programmers with Java or C++ background. Even though there 
> exists alternatives 
> (http://denis-sh.github.com/phobos-additions/unstd.multidimensionalarray.html), 
> this design decision and how to get around it when you really 
> desire a "rectangular" array could be explained in more detail 
> at http://dlang.org/arrays.html.
>
> - Static array versus dynamic array was one of the first traps 
> I stepped on 
> (http://forum.dlang.org/thread/jnu1an$rjr$1@digitalmars.com). 
> Until Jonathan M. Davis explained it in detail 
> (http://d.puremagic.com/issues/show_bug.cgi?id=8026#c4), I 
> pretty much considered it as "magic" that 
> "randomShuffle(staticArray);" did not sort the array while 
> "randomShuffle(staticArray[]);" did (the first call now gives 
> you an compile error, though). That static arrays are value 
> types while dynamic arrays are reference types may not be 
> obvious for those with primarily Java background.
>

Yes, Java have no value types, only reference types. This is 
actually a performance issue for 2 reasons :
  - You chase pointers, so you have cache miss and this is very 
costly on modern CPUs.
  - This is very GC unfriendly.

For instance, on a project at a previous work, we had an LRU 
cache into an application. We knew that most object should 
traverse the cache and get out very fast, when other will stick 
in it most of the time for reason that'd be too long to explain.

It lead to difficult to solve performances issues as while going 
through the LRU, object were considered as old by the GC and 
treated differently. As a consequence, the application generated 
a lot of garbage considered as old by the GC (when the GC assume 
that most objects dies young).

It required a lot of work to make that work, when using value 
type would have solved the whole this instantly.

> - When casting a value to an enum, there's no checking that the 
> value actually is a valid enum value. Don't think I ever found 
> a solution on how to check whether the value after casting is a 
> valid enum value, it hasn't been a pressing issue.
>

Very true. enum as they stand have some safety issue IMO.

> - Compiling where DMD can't find all modules cause a rather 
> cryptic error message. A solution is to make sure you specify 
> all source files when compiling.
>

dmd is really uneven with error messages. Some are purely 
awesome, and other are completely cryptic. A very "funny" one is 
when you use import instead of module (dmd complain about the 
module conflicting with itself).

>
> Wishlist:
> ---------
> - "void[T]" associative array (i.e. a "set") would be nice, can 
> be achieved with "byte[0][T]".
>

Don't get me started on AA !

> - "Foo foo = new Foo();" for global variables/class members. 
> Now you must "Foo foo; static this() { foo = new Foo(); }".

Yes, as it imply an heap allocation. It is an harder problem that 
it seems as all thoses object could reference themselves.


More information about the Digitalmars-d mailing list