Consistency, Templates, Constructors, and D3

David Piepgrass qwertie256 at gmail.com
Fri Aug 24 23:45:47 PDT 2012


> I've had a couple of ideas recently about the importance of 
> consistency in a language design, and how a few languages I 
> highly respect (D, C#, and Nimrod) approach these issues. This 
> post is mostly me wanting to reach out to a community that 
> enjoys discussing such issues, in an effort to correct any 
> mis-conceptions I might hold, and to spread potentially good 
> ideas to the community in hopes that my favorite language will 
> benefit from our discussion.

The points you raise are good and I generally like your ideas, 
although it feels a little early to talk about D3 when D2 is 
still far from a comprehensive solution. Amazing that bug 1528 is 
still open for example: 
http://stackoverflow.com/questions/10970143/wheres-the-conflict-here

Regarding your idea for merging compile-time and run-time 
arguments together, it sounds good at first but I wonder if it 
would be difficult to handle in the parser, because at the call 
site, the parser does not know whether a particular argument 
should be a type or an expression. Still, no insurmountable 
difficulties come to mind.

I certainly like the idea to introduce a more regular syntax for 
object construction (as I have proposed before, see 
http://d.puremagic.com/issues/show_bug.cgi?id=8381#c1) but you 
didn't say whether it would be allowed to declare a static method 
called "new". I'd be adamant that it should be allowed: the 
caller should not know whether they are calling a constructor or 
not. Also, I'm inclined to think that constructors should use 
"init", in keeping with tradition.

A couple inconsistencies that come immediately to my mind about 
D2 are

1. Function calling is foo!(x, y)(z) but declaration is foo(x, 
y)(int z)
    And the compiler doesn't always offer a good error message. 
I'm seeing
    "function declaration without return type. (Note that 
constructors are always named 'this')"
    "no identifier for declarator myFunction!(Range)(Range r)"
2. Ref parameters are declared as (ref int x) but are not allowed 
to be called as (ref x) -- then again, maybe it's not a real 
inconsistency, but I'm annoyed. It prevents my code from 
self-documenting properly.

Obviously, D is easy compared to C++, but no language should be 
judged by such a low standard of learnability. So I am also 
bothered by various things about D that feel unintuitive:

1. Enums. Since most enums are just a single value, they are 
named incorrectly.
2. immutable int[] func()... does not return an immutable array 
of int[]?
3. 0..10 in a "foreach" loop is not a range. It took me awhile to 
find the equivalent range function, whose name is quite baffling: 
"iota(10)"
4. Eponymous templates aren't distinct enough. Their syntax is 
the same as a normal template except that the outer and inner 
members just happen to have the same name. This confused me the 
other day when I was trying to understand some code by Nick, 
which called a method inside an eponymous templates via another 
magic syntax, UFCS (I like UFCS, but I might be a little happier 
if free functions had to request participation in it.)
5. The meaning is non-obvious when using "static import" and 
advanced imports like "import a = b : c, d" or "import a : b = c, 
d = e" or "import a = b : c = d".
6. the syntax of is(...)! It looks like a function or operator 
with an expression inside, when in fact the whole thing is one 
big operator. It's especially not obvious that "is(typeof(foo + 
bar))" means "test whether foo+bar is a valid and meaningful 
expression".

Making matters worse, the language itself and most of its 
constructs are non-Googlable. For example if you don't remember 
how do declare the forwarding operator (alias this), what do you 
search for? If you see "alias _suchAndSuch this" and don't know 
what it means, what do you search for? (one might not think of 
removing the middle word and searching for that).

I even have trouble finding stuff in TDPL e-book. The place where 
templates are discussed is odd: section 7.5 in chapter 7, 
"user-defined types", even though the template statement doesn't 
actually define a type. I know, I should just read the book 
again... say, where's the second edition? I got so disappointed 
when I reached the end of chapter 13 and it was followed by an 
index. No UFCS or traits or ranges mentioned in there anywhere... 
compile-time function evaluation is mentioned, but the actual 
acronym CTFE is not.

I also hope something will be changed about contracts. I am 
unlikely to ever use them if there's no option to keep SOME of 
them in release builds (I need them to work at all boundaries 
between different parties' code, e.g. official API boundaries, 
and it is preferable to keep them in all cases that they don't 
hurt performance; finally, we should consider that the class that 
contains the contracts may not know its own role in the program, 
so it may not know whether to assert or enforce is best). Plus, 
the syntax is too verbose. Instead of

    in {
      assert(x >= 0 && x < 100);
    },

I'd prefer just in(x >= 0 && x < 100). I'd rather not type "body" 
either. Speaking of verbosity -- breaks in switches. Nuff said.

Interestingly, the discussion so far has been all about syntax, 
not any significant new features. I'm thinking ... coersion of a 
class to any compatible interface (as in Go)? pattern matching? 
tuple unpacking? an attribute system? unit inference? compiler 
plug-ins? further enhanced metaprogramming? safe navigation 
operator? user-defined operators? first-class void type? If I 
were a compiler writer (and I want to be) the possibilities would 
be MADDENINGLY endless :)


More information about the Digitalmars-d mailing list