On Monday, 4 September 2017 at 03:26:23 UTC, EntangledQuanta
wrote:
Take a variant type. It contains the "type" and the data. To
simplify, we will treat look at it like
(pseudo-code, use your brain)
enum Type { int, float }
foo(void* Data, Type type);
The normal way to deal with this is a switch:
switch(type)
{
case int: auto val = *(cast(int*)Data);
case float: auto val = *(cast(float*)Data);
}
But what if the switch could be generated for us?
[...]
But, in fact, since we can specialize on the type we don't have
to use switch and in some cases do not even need to specialize:
for example:
foo(T)(T* Data) { writeln(*Data); }
is a compile time template that is called with the correct type
value at run-time due to the "magic" which I have yet to
introduce.
Note that if we just use a standard runtime variant, writeln
would see a variant, not the correct type that Data really is.
This is the key difference and what makes this "technique"
valuable. We can treat our dynamic variables as compile time
types(use the compile time system) without much hassle. They
fit naturally in it and we do not clutter our code switches. We
can have a true auto/var like C# without the overhead of the
IR. The cost, of course, is that switches are still used, they
are generated behind the scenes though and the runtime cost is
a few instructions that all switches have and that we cannot
avoid.
To get a feel for what this new way of dealing with dynamic
types might look like:
void foo(var y) { writeln(y); }
var x = "3"; // or possibly var!(string, int) for the explicit
types used
foo(x);
x = 3;
foo(x);
It sounds like what you are describing is a sum type. There is an
implementation of one in the standard library,
std.variant.Algebraic, as well as several alternative
implementations on code.dlang.org, including my own, "sumtype"
[1].
Using sumtype, your example would look like this:
alias Var = SumType!(string, int);
void foo(Var y) {
var.match!(
(value) { writeln(value); } // template lambda
);
}
Var x = "3";
foo(x);
x = 3;
foo(x);
The match method takes a list of functions as template arguments,
and generates a switch statement that maps each possible type of
Var to one of those functions. All type checking is done at
compile time.
[1] https://code.dlang.org/packages/sumtype