New programming paradigm

Biotronic via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Thu Sep 7 15:53:31 PDT 2017


On Thursday, 7 September 2017 at 16:55:02 UTC, EntangledQuanta 
wrote:
> Sorry, I think you missed the point completely... or I didn't 
> explain things very well.

I don't think I did - your new explanation didn't change my 
understanding at least. This indicates I'm the one who's bad at 
explaining. Ah well.

The point of my post was mostly to rewrite the code you'd posted 
in a form that I (and, I hope, others) found easier to understand.

> I see no where in your code where you have a variant like type.

True. I've now rewritten it to use std.variant.Algebraic with 
these semantics:

auto foo(T1, T2)(T1 a, T2 b, int n) {
     import std.conv;
     return T1.stringof~": "~to!string(a)~" - "~T2.stringof~": 
"~to!string(b);
}

unittest {
     import std.variant;
     Algebraic!(float, int) a = 4f;
     Algebraic!(double, byte) b = 1.23;

     auto res = varCall!foo(a, b, 3);
     assert(res == "float: 4 - double: 1.23");
}

template varCall(alias fn) {
     import std.variant;
     auto varCall(int n = 0, Args...)(Args args) {
         static if (n == Args.length) {
             return fn(args);
         } else {
             auto arg = args[n];
             static if (is(typeof(arg) == VariantN!U, U...)) {
                 foreach (T; arg.AllowedTypes) {
                     if (arg.type == typeid(T))
                         return varCall!(n+1)(args[0..n], 
arg.get!T, args[n+1..$]);
                 }
                 assert(false);
             } else {
                 return varCall!(n+1)(args);
             }
         }
     }
}

Sadly, by using std.variant, I've given up on the elegant 
switch/case in exchange for a linear search by typeid. This can 
be fixed, but requires changes in std.variant.

Of course, it would be possible to hide all this behind compiler 
magic. Is that desirable? I frankly do not think so. We should be 
wary of adding too much magic to the compiler - it complicates 
the language and its implementation. This is little more than an 
optimization, and while a compiler solution would be less 
intrusive and perhaps more elegant, I do not feel it provides 
enough added value to warrant its inclusion.

Next, I'm curious about this code:

> void bar(var t)
> {
>     writeln("\tbar: Type = ", t.type, ", Value = ", t);
> }
> 
> void main()
> {
>    bar(3); // calls bar as if bar was `void bar(int)`
>    bar(3.4f); // calls bar as if bar was `void bar(float)`
>    bar("sad"); // calls bar as if bar was `void bar(string)`
> }

What does 'var' add here, that regular templates do not? (serious 
question, I'm not trying to shoot down your idea, only to better 
understand it) One possible problem with var here (if I 
understand it correctly) would be separate compilation - a 
generated switch would need to know about types in other source 
files that may not be available at the time it is compiled.

Next:

> var foo(var x)
> {
>    if (x == 3)
>        return x;
>    return "error!";
> }

This looks like a sort of reverse alias this, which I've argued 
for on many occasions. Currently, it is impossible to implement a 
type var as in that function - the conversion from string to var 
would fail. A means of implementing this has been discussed since 
at least 2007, and I wrote a DIP[1] about it way back in 2013. It 
would make working with variants and many other types much more 
pleasant.

[1]: https://wiki.dlang.org/DIP52


More information about the Digitalmars-d-learn mailing list