March 25, 2019
In functional programming languages there is generally a way to extending objects completely through inheritance.

Suppose for example that one has a class hierarchy like

 Person
    |
    v
 Profile
    |
  Image


which is like

class Person;
class Profile : Person { Image[] images; }
class Image;

This is all standard oop.

Suppose one builds a business model using this, we will represent it simply as

Person[] objects;

and one can think of it just as a set of people who have profiles(info) with some images

Now, suppose we would like to extend our business model to include a graphical viewer around it. We do not want to touch the business model, it all works. We just want to add functionality "on top" of the model with the least amount of plumbing. We definitely do not want to have to add a lot of code to hook up the visual side by having to mimic the business model, it's basically all there.

We want a visual model that sort sort of parallels the business model:


 VisualPerson
      |
      v
 VisualProfile
      |
 Visual Image


These new types include visual information that is only relevant to the visual side and have nothing to do with the business side, such as the xy coordinates for the image to be displayed, a draw routine that will "draw" the person on the screen, etc.


The key here is that the visual hierarchy MUST parallel the business model and be a drop in replacement for the business model where ever it is used(which leverages the oop side of things).

So if some external app uses our Person, we can instead just drop in VisualPerson and with little work get a visualization of that person in the external app.

This requires the hierarchy to be:

class VisualPerson : Person { Person p; mixin(Wrap!Person("p")); }
class VisualProfile : VisualPerson { Profile p; VisualImage[] images; mixin(Wrap!Profile("p")); }
class VisualImage : Image { Image i; mixin(Wrap!Image("i")); }

Note the extensions and transformations.

Any where a Person is used, a VisualPerson can be used. Visualization simply "extends" non-visualization, but it only adds new structure, it does not remove structure.

Through the power of oop, if Person is used somewhere, we can simply alter the code or use an abstract factory to turn it in to a visualization:

Graphics g = new Graphics();
Person p = new Person("Ken")
Person p = new VisualPerson(Person("Ken"), g);

And whatever app that was written with Person in mind will now have visual capabilities(at least in theory, a little work will generally be required to hook up the graphical system).

In a functional language this is very easy to handle by using functors and fmap which translate between the two structures the various components when ever they are used(recursively, so if a VisualPerson is the object, fmap will use the fmap of derived objects to map their structure so everything gets mapped. There is a one to one correspondence between Visual and Non-Visual, Every Non-Visual structural element has a corresponding Visual "wrapper"(that may not add anything new))).

We can achieve similar behavior using mixin(Wrap!X("x")); and the composition pattern but it is rather ugly.

Ideally there would be a simple way to extend a structure that just provides the necessary linkage:

Hypothetically:

class VisualPersonEx : Person
{

    void  DisplayPerson();
}

class VisualProfileEx : Profile
{

}

class VisualImageEx : Image
{

}



VisualPerson = Extend!(Person,VisualPersonEx, VisualProfileEx, VisualImageEx);

And Extend takes care of hooking up and transmogrifying what is required to make everything work.



In D, I'm unsure how to find a nice way to go about handling this. I do not want to create duplicate the business structure myself since it is quite large. I simply want to provide the additional structure around it exactly where it is needed.


One can see that it requires one to use composition and forwarding

What I am trying to do is functionally extend a model to an extended model and only add whatever additional functionality that is required without as minimum plumbing as I possibly can to extend the model. Since D does not have the concept of models(large scale multi-faceted compound objects) it is not so easy. In functional languages one can specify such models more naturally and do away with a lot of the plumbing, in D, I don't know? Maybe there is something out there or an easier way than what I have mentioned?

The main thing here to recognize is that when extending models, there is a uniform and deterministic process. Every type in the hierachy will extend to a new type that can be plugged in(composition) and every new type that uses an "old" type will actually use the new type instead.[E.g., VisualProfile uses Person, but since it's a new type it actually uses VisualPerson which exists. Essentially `uses` is uniformly extended to create wrapper of a model just as we can wrap an object]

Ideally D would have something like
NewModel = WrapModel!Model;

And then one just adds the new functionality to NewModel somehow.

And then we could do

NewNewModel = WrapModel!NewModel

which further extends the model.

Each time it encapsulates the old model.

This is analogous to having inheritance of models. Eventually, of course, we would want n-dimensional model mapping so that collections("classes") of models could be extended just as we can extend a class now using inheritance.

Is anything like this feasible in D?  [Remember, it's not just about doing it, it's about doing it optimally = little plumbing as possible]






March 25, 2019
On Monday, 25 March 2019 at 17:13:45 UTC, Craig wrote:
> [...]

Are you aware of alias this?
https://dlang.org/spec/class.html#alias-this

As long there is a 1:1 relationship, this works well. There is a DIP, to add multiple alias this to the language.