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