Rant after trying Rust a bit
Tofu Ninja via Digitalmars-d
digitalmars-d at puremagic.com
Sat Jul 25 04:12:34 PDT 2015
On Saturday, 25 July 2015 at 10:01:43 UTC, Walter Bright wrote:
> Phew, finally, someone understands what I'm talking about! I'm
> really bad at explaining things to people that they aren't
> already familiar with.
>
> I'm not sure, but I suspect this problem may cripple writing
> generic library functions that do one operation and then
> forward to the next (unknown in advance) operation in a chain.
>
> It also may completely torpedo Andrei's Design By Introspection
> technique.
Actually I don't think the problem you state is actually a
problem at all, even disregarding my previous argument(which is
still think is valid). The key point is that it would be opt-in
and it would trickle down, not up. Normal templates without the
concept/traits/interface things would still be able to call
functions with the extra constraints with out needing to add it
to them selves.
For instance, say the syntax to specialize on one of these
concept/traits/interface things was the same as specializing on a
class, eg:
void foo(T : inputRange)(T x){}
Calling foo from any where would still be the same, even calling
it from other templates with out the concept/traits/interface
things. eg the following would work:
void bar(T)(T x){ foo(x); }
Because bar is a normal template, it still has no choice but to
assume that T can do any thing we ask it to do, because that is
what we have always done with templates. So the template happily
assumes that passing x into foo will work. If for some reason you
pass a type in that is not an inputRange, then it will fail at
instantiation. So far it is the same as the constraints we have
now.
Ok, here is where it is different.
In side of foo, it would be illegal to do anything other than
inputRange stuff with x. For instance the following would be
illegal:
void foo(T : inputRange)(T x)
{
x.something(); // ERROR!
}
The real kicker here, is that THAT error can be detected without
ever instantiating foo. No need to rely on unittests, which may
or may not catch it depending on which types we use.
Ok now take it a step further. Say we have the following:
void foo(T : inputRange)(T x)
{
bar(x); // ERROR!
}
void bar(T : someOtherInterface)(T x){}
The previous would error! Why? Because foo only assumes x can do
inputRange things, and when you pass it into bar it asks it to do
someOtherInterface which it doesn't know it can do! This all
would still error with out every instantiating the template!
Also the following should also error:
void foo(T : inputRange)(T x)
{
bar(x); // ERROR!
}
void bar(T)(T x) if(isSomeOtherInterface!T) {}
Why? Because from inside foo, it is only assumed that x can do
inputRange things, when it gets passed into bar the constraint
will ask it to do non inputRange things and fail! Still with out
foo being instantiated! Even something like the following should
error:
void foo(T : inputRange)(T x)
{
bar(x); // ERROR!
}
void bar(T)(T x) { x.something_inputranges_dont_have(); }
This would error for the same reasons as before, bar asked x to
do non input range things. In contrast the following would be ok!
void foo(T : inputRange)(T x)
{
bar(x); // Ok
}
void bar(T)(T x) { foreach(i;x){} }
That still works because it is known that x can do inputRange
things, so its ok! Woo!
This is awesome right? All these errors being caught without ever
instantiating the templates. You should still instantiate them
and test them, but the value is that the errors were caught
sooner, with out even instantiating them.
The main difference here is that a normal template assumes that a
type can do anything until it actually gets instantiated. Add
some constraints(the normal ones we have now) and you can filter
for things that don't do X, but you still assume that the type
can do any thing else in addition to X. On the other hand, the
concept/traits/interface things would be as conservative as
possible and only assume a type can do what its
concept/traits/interface things say it can do.
In summery, the concept/traits/interface things would not require
them to applied to the whole tree. Doing so would break how
templates work now and really just does not make sense unless
things were being redone from scratch. They are opt-in! In
addition to that, they catch a bunch of bugs in templates before
they are ever instantiated! This is a good thing.
More information about the Digitalmars-d
mailing list