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