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.

Reply via email to