Generically call a function on Variant's payload?
Nick Sabalausky (Abscissa)
SeeWebsiteToContactMe at semitwist.com
Mon Aug 20 19:38:13 UTC 2018
On 08/19/2018 11:31 PM, Paul Backus wrote:
>
> You are basically reinventing OOP here.
>
Yes, I am. Deliberately, in fact. Class inheritance is my backup plan,
though.
My use-case is actually very, very similar to std.digest:
There are various benefits to using a template-and-constraint based
interface. But one notable downside is the inability to handle the
situation where the actual type needed is only known at runtime. In
std.digest, this dilemma is dealt with by duplicating the entire
interface in BOTH template/constraint AND class-inheritance varieties.
Additionally, an important thing to note in the case of std.digest is
that `isDigest!T` returns FALSE for types using the OOP version of the
interface. I think there is (arguably) a certain merit in that:
The OOP interface obviously uses classes, whereas (in order to obtain
the full potential benefits of a template-and-constraint approach) the
template interface uses (and even requires) structs. Because of this,
instances should be constructed differently ("T instance;" vs "T
instance = new T();"). Thus, any generic code that wants to handle ANY
digest type must be very careful to mind this distinction whenever
creating new instances. Presumably, this may be why std.digest chose to
NOT let OO digests satisfy the template-oriented isDigest.
And then std.digest also needs WrapperDigest, needed to convert a
template-style digest to OO-style.
So...while std.digest succeeds at offering the best-of-both-worlds
between template and OO approaches, it also creates a whole new mess via
completely duplicated interfaces that aren't 100% compatible.
I want to see if I can do better.
So back to the root of the problem:
We have a bunch of types, including user-defined types we don't have
advance knowledge of. And we need a type which can hold any of them at
runtime.
AFAIK, there are two classic ways to do that: One is OOP, the other is
an unbounded discriminated union (a variant). Unlike class-based
inheritance, a variant CAN be implemented as a struct. So, at least in
theory, a variant-based type could potentially be made which implements
the *true* template-based interface, eliminating the need for duplicate
APIs and the mess that entails.
There are a bunch of discriminated union types available for D, but the
only one I'm aware of that *doesn't* require a finite-sized list of
types known ahead-of-time is Phobos's Variant. The only problem is
calling a function on a type not already known ahead-of-time. Maybe
that's unsolvable? If so, then I'll fallback to the std.digest approach.
But I'd prefer to avoid that, if possible.
More information about the Digitalmars-d-learn
mailing list