New programming paradigm

DigitalDesigns DigitalDesigns at gmail.com
Sun Jun 3 14:57:37 UTC 2018


On Sunday, 3 June 2018 at 09:52:01 UTC, Malte wrote:
> On Saturday, 2 June 2018 at 23:12:46 UTC, DigitalDesigns wrote:
>> On Thursday, 7 September 2017 at 22:53:31 UTC, Biotronic wrote:
>>> [...]
>>
>> I use something similar where I use structs behaving like 
>> enums. Each field in the struct is an "enum value" which an 
>> attribute, this is because I have not had luck with using 
>> attributes on enum values directly and that structs allow 
>> enums with a bit more power.
>>
>> [...]
>
> You might want to have a look at 
> https://wiki.dlang.org/Dynamic_typing
> This sounds very similar to what you are doing. I never really 
> looked into it, because I prefer to know which type is used and 
> give me errors if I try to do stupid things, but I think it's a 
> cool idea.

No, this is not what I'm talking about, although maybe it could 
be related in some way.

What I am talking about is hooking up a runtime variable that can 
take a few values, such as from an enum and have those be mapped 
to a compile time template value.

This way you get full static time checking of runtime code. Seems 
impossible? It's not!

What it does is leverage D's meta programming engine to deal with 
all the routine possiblities.

A large switch statement is what makes the runtime to compile 
time magic happen

int x;

switch(x)
{
     default: foo!void();
     case 0: foo!int();
     case 1: foo!double();
     etc...
}

See how the switch maps a runtime value x to a templated function 
foo?

we then can handle the x values with foo

void foo(T)()
{
    // if x = 0 then T = int
    // if x = 1 then T = double


}

But inside foo we have T, the template variable that is the 
compile time representation of the dynamic variable x. Remember, 
x's value is unknown at compile time... the switch is what maps 
the runtime to the compile time.

But in foo, because we have T, the type system all works fine.

What makes this very useful that we can call templated functions 
using T and the meta engine will pick the right template function 
specialization.

e.g.,

void bar(S)()
{

}


can be used inside foo by calling bar!T(). It doesn't seem like 
much here if you had to use x it would be a pain. Either you 
would have to manually create switches or create a rats nest of 
if statements. But we never have to worry about that stuff when 
using the above method because it is exactly like programming at 
compile time as if x a compile time value(like say, just int).

It works great when you have several template variables and just 
want everything to work together without having to go in to much 
trouble:


foo(A,B)()
{
    B b = 4;
    bar!(A)(b)
}


suppose A can come from int, double, and B from float and long

That is 4 different combinations one would normally have to 
represent. Not a big deal until you have to handle every 
combination.


Suppose you are working with void arrays. They contain types but 
you don't know the type except after compile time.

Without using this technique you have to use casts and tricks and 
you'll find out if you screwed up some typing stuff at runtime. 
Using this technique you will not have a void array but a T[] 
with T being any of the possible types that you specify using 
UDA's.

if you could

if (x == 0)
{
     foo(cast(int[])a);
} else

if (x == 1)
{
     foo(cast(double[])a);
} else


but I can do that with one line which simply generates the switch 
for me. Really all I'm doing is hiding the switch so it all looks 
like some magic is happening in one line. But the fact that it 
becomes really simple to do seems to open up the use of it and 
conceptually on can then think of "x" as a compile time variable 
that can take on several possibilities.





More information about the Digitalmars-d-learn mailing list