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

Reply via email to