On Sunday, 26 July 2015 at 23:21:50 UTC, Walter Bright wrote:
If the template constraint is 'isInputRange', and you pass it
an 'InputRange' that is nothing beyond an input range, and it
compiles, it is JUST AS GOOD as Rust traits, without needing to
add 'isInputRange' to every template up the call tree.
In fact, I do just this in my D dev projects. I have a set of
mock ranges that match each of the range types.
That is not enough, it has been covered. It is clear that this is
what needs to be done for good testing. It is also clear and
explained in this thread that this is not enough.
The problem is the exact same as for dynamic typing and
unitests. A dynamically
typed function that expect a string can be test exhaustively
with warious string
passed as arguments. Still, none knows what happen when passed
an int, float,
array, object or whatever. Worse, it is either going to blow
up in some
unexpected way or not explode and do random stuff.
Flatly no, it is not at all the same. Dynamic typing systems do
not have constraints. Furthermore, dynamic typed languages tend
to do random s**t when presented with the wrong type rather
than fail. (Such as concatenating strings when the code was
intended to do an arithmetic add.) D does not, it presents the
user with a compilation error.
That is blatantly false and show more ignorance than anything
else. For the precise example, concatenate with + is know to be
bad in dynamic typing for this very reason. Even PHP got around
that trap and pretty much only javascript got into that road.
You'll find noone defneding this outside the Node.js crowd, but
once you start thinking that a monothreaded event loop is the
definition of scalable, you are already lost for science anyway.
But more generally there is a point. Dynamic languages tends to
do random shit rather than failing. Hopefully, some won't. For
instance python will fail hard rather than do random stuff when
passed the wrong type.
If that was the problem faced, then using a type system would be
pointless. Using something like python is sufficient.
The same way, instantiate your template with something it
doesn't expect and you
get absurdly complex errors (and it is getting worse as phobos
get more and more
"enterprise" with Foo forwarding to FooImpl and 25 different
helpers).
This is incorrect. In my D project development, when I send the
wrong thing, I get a list of the template instantiation stack.
Which is often 3 pages long.
The bottom gives the method not found, and the stack gives how
it got there. I find it adequate in that it doesn't take much
effort to figure out where things went wrong.
That is learned helplessness. This is bad and we should feel bad
to propose such a user experience. There are reasons why template
are frowned upon by many devs, and this is one of them.
I even heard Andrei suggest at a conf to pipe the output of the
compiler to head (he was talking about C++, but D suffer from the
same problem in that regard). Yes it works, and yes you can
eventually make sens of the error, but that is terrible user
experience.
BTW, when you discover that a constraint is wrong on a Phobos
template, please file a bug report on it.
It is not just phobos, but everybody's code. Why all this need to
be done manually when the compiler could do it for us ?
Isn't it why we use computer in the first place ?
If I follow your post, one have to maintain a set of minimal mock
to test instantiations, a constraint for the template and a body,
the 3 of them requiring to be kept in synch over time while
nothing checks it is.
That is completely unmaintainable.
The problem is the same, will it fail at call
site/instanciation site with "I
expected X you gave me Y" or will it fail randomly somewhere
down the road in
some unrelated part of the code, or worse, not fail at all
when it should have ?
If the constraint is InputRange, and the body assumes
ForwardRange, and I pass it a ForwardRange, and it works, how
is that 'worse'?
Maybe now my complexity is quadratic ? Maybe it doesn't do what
it is supposed to do anymore, but else ?