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

H. S. Teoh hsteoh at quickfur.ath.cx
Wed Mar 27 10:05:08 PDT 2013


On Wed, Mar 27, 2013 at 04:34:19PM +0100, Vidar Wahlberg wrote:
[...]
> - 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.

This is true. Sometimes you really *do* want to know what the return
type of an auto function is. However, you can work around this by using
typeof:

	auto func() {
		return mysteriousType();
	}

	void main() {
		alias RetType = typeof(func());

		// Look, ma! I can use a type without knowing what it
		// is!
		RetType t = func();
		...
	}


> While you may be able to find out what "bar" is by digging in the
> source code, it can still be difficult to find.

I think this is a bad solution. A library user shouldn't need to look at
library source code to figure out what a return type is.


> 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.

I find this solution a bit cumbersome. D already has a built-in typeof
operator, there's no need to write tons of wrappers everywhere just to
get a return type out. I would write it like this:

	class C {
		// Capture the return type of std.regex.match
		alias MatchResult = typeof(std.regex.match("", ""));

		// Now you can store it
		MatchResult result;

		this(string target, string regex) {
			result = std.regex.match(target, regex);
		}
	}


> 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.

We really need rectangular arrays in Phobos. Denis has written one, as
you linked above, and I've written one, too (which is similar to Denis'
version). But this is such a common usage that we really should have a
library module for it.

Note, however, that if all but 1 of the dimensions are known, then you
*can* have rectangular arrays:

	// This is a rectangular array
	int[3][4][5] rect;

See also: http://wiki.dlang.org/Dense_multidimensional_arrays


> - 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.

Well, the documentation needs to be improved in this regard, that's for
sure. But language-wise, there's really nothing wrong with it (it's not
a sin to be different from Java).


> - 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.

Yeah, I find this to be questionable behaviour too. But then again, in
D, one is expected to use std.conv for conversions (casting is generally
not recommended unless there's no other way to do it), and std.conv.conv
does check for valid enum values:

	enum A { abc = 100, def = 200 }
	A a;
	writeln(a);	// prints "abc"

	a = to!A(150);	// this throws a runtime exception: 150 is not
			// in the enum.


> - 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.

You could use rdmd, which I believe automatically scans for all source
files you depend on.


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

I think we should make a Phobos module for this. I, for one, found
myself needing such a type.


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

Yeah, this is an irksome limitation. Though, it does have the benefit of
not letting you do something that incurs runtime-cost without being
explicit about it. Still, it is cumbersome to have to use static this()
all over the place. It would be nice for the compiler to automatically
lower such things into implicit ctor calls.


T

-- 
A bend in the road is not the end of the road unless you fail to make
the turn. -- Brian White


More information about the Digitalmars-d mailing list