Recursive Algebraic
Mr.Bingo
Bingo at Namo.com
Sat Jun 30 12:05:54 UTC 2018
The problem is that it seems that when one has a parameterized
type, you must completely specify the parameters when using
Algebraic,
Algebraic!(T, Vector!int, Vector!(double, 3), Vector!(double, 3),
...)[] data;
to be able to encapsulate an Algebraic on Vector(as a collection
of all fixed point evaluations).
What I'd rather do is something akin to
Algebraic!(T, Vector!(T, N))[] data;
or, hell, even just
Algebraic!(T, Vector)[] data;
Since A!B bears no relationship to A!C except their name, this is
not necessarily a good idea, but neither is having to explicitly
express all kinds.
I imagine there is some trick using inheritance,
Maybe
class X;
class A(int N) : X;
then
Algebraic!(T, X)[] data;
only works if Algebraic handles inheritance and checks with
handlers for specificity.
The problem with D's type system is that it does not allow one to
express sets of types, which is a special type in and of itself,
except in some specific cases such as using is(,...).
Here is a snippet of code
https://dpaste.dzfl.pl/8ff1cd3d7d46
That shows that an algebraic does not handle inheritance.
if Y : X then we'd expect
Algebraic!(T, Y) : Algebraic!(T, X)
and for there to be no problem.
For this not to be a problem two things need to be known:
1. To be able to get the type of X and Y
2. To be able to determine if Y : X.
D provides the ability to determine if a type inherits from
another at runtime using classinfo which every D class contains
and it's inheritance relationships, solving problem 2.
Problem 1 is to be able get the types of an object in a way that
can be related to D's pre-existing methods for comparing type
info. Variant stores the typeid so Problem 2 is solved!
Therefor, we can safely say that Algebraic can easily deal with
inheritance. I am not familiar enough with the D internals to
provide a fix. Anyone familiar with Algebraic should be able to
write a few lines of code to allow for inheritance checking(or
even complex patterns using a lambda to determine if a type is in
the Algebraic. This becomes a function on the typeid's and
classinfo's which is determined by the user.
Algebraic!((x) {
if (is(x.type == typeid(y)))
return x.get!X;
return defaultX(x);
}, int)
Where the above algebraic allows any object that has the same
typeid of some object y or some object that has the same type as
defaultX(x)(which could be anything) or an int.
One could even do strange things like
Algebraic!((x) {
if (rand1(0.5)
return x;
return 1;
}, int)
which, remembering that this lambda is run at runtime to
determine if an object stored in the variant is "in the
algebraic", will allow any object to pass 50% of the time(and
potentially crash when some code gets an object it can't handle.
For example, if the above algebraic was to work only integral
types then it would be problematic when x was a non integral
type(but maybe floating point t types would work). This is
assuming some handler was called, which wouldn't be because there
is no handler that exists handle the non integral types.
Hence things like visit would have to allow, if the lambda was
specified, a way to fall through.
a.visit!((int i) => 4*i, (Object o) => return 2);
Which, 50% of the time would return 2 and the other half of the
time it would return 4.
Allowing functions to specify Algebraic relationships gives far
more power. D seems to already have everything available to do
it. For example, the original problem of inheritance
relationships can easily be expressed:
Algebraic!((x) {
if (doesDerive!Y(x))
return cast(Y)x;
if (doesDerive!Z(x))
return new Q(x);
return null;
}, int)
The algebraic handles an object derived from Y, Q, and int.
a.visit!((int i) => 4*i, (Y) => 2, (Q q) => q.value);
More information about the Digitalmars-d-learn
mailing list