July 27, 2019
On Saturday, 27 July 2019 at 04:26:01 UTC, Mike Franklin wrote:
>
> struct IOStream
> {
>     IStream i;
>     OStream o;
>
>     // Generating the following functions can be automated with D's awesome
>     // metaprogramming facilities
>     string read() { return i.read(); }
>     void write(string s) { o.write(s); }
>
>     // But how do we implicitly convert from `IOStream` to `IStream` or
>     // `OStream` without `alias this`, `opImplicitCast` or some other?
>     alias i this;
>     alias o this; // mulitple `alias this` currently not implemented, so
>                   // this doesn't work
> }

I was thinking of something simpler. And also new to the language, not that could or should be implemented by lowering (specially not lowering to alias this).

Again leaving multiple aside:

    interface IPrintable
    {
        string toString();
    }
    struct XY : IPrintable
    {
        @disable this();
        real x, y;
        string toString() { /*...*/ }
        // implicitly final always; virtual illegal in structs.
    }
    struct ParallelXY : XY
    {
        uint universe;
        void warp() { ++universe; }
    }

Implement the same simple thing (including @disable this() for every type) with current D (alias this) and see how much more typing and overhead.
July 26, 2019
On Fri, Jul 26, 2019 at 9:30 PM Mike Franklin via Digitalmars-d <digitalmars-d@puremagic.com> wrote:
>
> On Saturday, 27 July 2019 at 04:15:38 UTC, XavierAP wrote:
>
> > I think struct inheritance (with no virtual dispatch) may be
> > good for D. Has no one ever tried a DIP?
>
> I'm formulating one, but I haven't gotten very far yet.  Others have also mentioned interest.

I would love to see this. Please do it.

> Walter is quite opposed to
> implicit casting (https://github.com/dlang/dmd/pull/10161) so I
> was thinking of a different strategy that would use keep the
> implicit casting feature of `alias this` but defer the forwarding
> to members to D's metaprogramming facilities.

The obvious counterpart to `@implicit` constructors is probably
`@implicit` cast operators.
Those aren't quite the same as "alias this stuff into 'this' scope",
and at that very specific semantic, I think `alias this` is
occasionally useful, but if you're just trying to emulate implicit
construction or implicit casting, then I think there are better and
more deliberate ways to do that, possibly with `@implicit`.
July 27, 2019
On Saturday, 27 July 2019 at 04:26:01 UTC, Mike Franklin wrote:
> On Saturday, 27 July 2019 at 04:15:38 UTC, XavierAP wrote:
>
>> I think struct inheritance (with no virtual dispatch) may be good for D. Has no one ever tried a DIP?
>
> I'm formulating one, but I haven't gotten very far yet.

I think DIPs have much better chances if you separate them into single inheritance and eventually a second one to add multiplicity.

Multiple inheritance is controversial enough on its own. If you merge it into any other DIP I am willing to bet anything the DIP will end up dead...
July 27, 2019
On Saturday, 27 July 2019 at 06:58:58 UTC, XavierAP wrote:

> Multiple inheritance is controversial enough on its own. If you merge it into any other DIP I am willing to bet anything the DIP will end up dead...

I'm keeping that in mind.  But we need to be more precise in our terminology.  Yes, multiple inheritance has its problems, but what I'm proposing is NOT multiple inheritance.  It is simply struct composition as it should be.

We keep espousing "prefer composition over inheritance" but then the programming languages we design offer us precious little to actually do the right thing.  I think D can be the first language to finally do composition right with this feature.

Mike
July 27, 2019
On Saturday, 27 July 2019 at 05:09:18 UTC, Manu wrote:

> The obvious counterpart to `@implicit` constructors is probably
> `@implicit` cast operators.
> Those aren't quite the same as "alias this stuff into 'this' scope",
> and at that very specific semantic, I think `alias this` is
> occasionally useful, but if you're just trying to emulate implicit
> construction or implicit casting, then I think there are better and
> more deliberate ways to do that, possibly with `@implicit`.

I would be perfectly happy with `opImiplicitCast` or some way to have implicit constructors.  But Walter has already voiced his disapproval of that (See the comments in https://github.com/dlang/dmd/pull/10161 for the disappointment), so our choices are getting slim.  I'm trying to find something he would be willing to approve. If you have any ideas, I'm all ears.

I'm currently trying to collect ideas from others.  Alex (12345swordy) gave me some good ideas yesterday, and I'm internalizing them.

Here's what I'm thinking right now:

Walter opposes implicit casts, but we already have `alias this`.  `alias this` currently does 2 things: (1) It simulates an implicit cast (2) It forwards unresolved symbols to the aliased member.  The problem with `alias this` is (2), and that causes a lot of resolution bugs and other "weird sh**". (1) is fine.

(1) is all we need because we have enough metaprogramming facilities to implement (2) in the library.  What I'm thinking is that we create a more limited `alias this` that only does (1).  I'm thinking about syntax like this to distinguish it from the existing `alias this` feature.

struct Base
{
    void method1() { }
    void method2() { }
}

struct Derived
{
    Base b;
    alias b;  // `this` is implicit.  That will distinguish it from
              // `alias b this` as the more limited `alias this` I
              // proposed above.  It is an error to use both forms.

    mixin ForwardPublicMembers!(b);
    // The above mixin is a utility in the library that generates the
    // following
    //
    // void method2()
    // {
    //     b.method2();
    // }
    //
    // void method2()
    // {
    //     b.method2();
    // }
}

void foo(Base b) { }

void main()
{
   Derived d;
   foo(d);    // Works because (1) -- the implicit casting behavior of
              // `alias this` is retained with `alias b`
}

This will keep the current `alias this` working as is, but allow us to introduce a new form.  Why I think I might be able to make the case to Walter...

1.  It's not the wild west of `opImplicitCast` or implicit constructors, which Walter already says he won't approve.
2.  It's not much different from what we have today with `alias this`, so it's not a radical change, which I think Walter will appreciate.
3.  If users migrate away from `alias b this;` and prefer `alias b;` then we may be able to deprecate the `alias b this` form along with all of its "weird sh**" resolution problems and bugs.  I think Walter will appreciate that also.
4.  In the long term, if `alias this` is deprecated we will be able to delete a huge mess of complexity from the compiler, and I think that will be appealing to Walter as well.
5.  It doesn't break any existing code.  `alias b this` will still work until we decide we don't want to support it anymore.  This is an "addition-only" change.

I may be wrong with my speculation here, but given the constraints Walter has voiced, it's the best I can think of.  Either that or we have to try to convince Walter to embrace implicit casting, and you all know how that will likely end up.  The only other saving grace may be Atila.

Mike
July 27, 2019
On Saturday, 27 July 2019 at 05:09:11 UTC, XavierAP wrote:

> I was thinking of something simpler. And also new to the language, not that could or should be implemented by lowering (specially not lowering to alias this).
>
> Again leaving multiple aside:
>
>     interface IPrintable
>     {
>         string toString();
>     }

I like the idea of using interfaces, but I'm not sure how to implement such a thing for structs.  Is it just a compile-time contract?  How does it work at runtime when we call a function like `void foo(IPrintable p);` with an instance of `XY` or `ParallelXY`?

>     struct XY : IPrintable
>     {
>         @disable this();
>         real x, y;
>         string toString() { /*...*/ }
>         // implicitly final always; virtual illegal in structs.
>     }
>     struct ParallelXY : XY
>     {
>         uint universe;
>         void warp() { ++universe; }
>     }
>
> Implement the same simple thing (including @disable this() for every type) with current D (alias this) and see how much more typing and overhead.

Are you suggesting the body of `XY` simply be copied into `ParallelXY`?  I think that can already be done with template mixins.
July 27, 2019
On Saturday, 27 July 2019 at 09:38:20 UTC, Mike Franklin wrote:
> On Saturday, 27 July 2019 at 05:09:11 UTC, XavierAP wrote:
>
>> I was thinking of something simpler. And also new to the language, not that could or should be implemented by lowering (specially not lowering to alias this).
>>
>> Again leaving multiple aside:
>>
>>     interface IPrintable
>>     {
>>         string toString();
>>     }
>
> I like the idea of using interfaces, but I'm not sure how to implement such a thing for structs.  Is it just a compile-time contract?  How does it work at runtime when we call a function like `void foo(IPrintable p);` with an instance of `XY` or `ParallelXY`?


You reminded me of the existence of this:

https://github.com/rikkimax/DIPs/blob/master/DIPs/DIP1xxx-RC.md

July 27, 2019
On Saturday, 27 July 2019 at 08:32:07 UTC, Mike Franklin wrote:
>
> but what I'm proposing is NOT multiple inheritance.  It is simply struct composition as it should be.

Ah well I was referring to simple plain old inheritance, so it'd be a separate topic/DIP. My question was whether a DIP about simple struct inheritance, and I interpreted Manu's past thread as requesting this (possibly among or together with other features); but I had misunderstood at least the former.

> We keep espousing "prefer composition over inheritance" but

I see the point in that statement, but I don't subscribe 100%. There's a pitfall in inheritance when you make too complex hierarchies, that are too inflexible to redesign. In this case if you had implemented the same from composition (e.g. entity-component-system architecture) it would be more flexible/better.

But those cases don't mean imo that inheritance is anathema or never useful. Every feature can be abused (even templates, or metaprogramming ;)

> I think D can be the first language to finally do composition right with this feature.

Sounds interesting.
July 27, 2019
On 27/07/2019 10:46 PM, aliak wrote:
> On Saturday, 27 July 2019 at 09:38:20 UTC, Mike Franklin wrote:
>> On Saturday, 27 July 2019 at 05:09:11 UTC, XavierAP wrote:
>>
>>> I was thinking of something simpler. And also new to the language, not that could or should be implemented by lowering (specially not lowering to alias this).
>>>
>>> Again leaving multiple aside:
>>>
>>>     interface IPrintable
>>>     {
>>>         string toString();
>>>     }
>>
>> I like the idea of using interfaces, but I'm not sure how to implement such a thing for structs.  Is it just a compile-time contract?  How does it work at runtime when we call a function like `void foo(IPrintable p);` with an instance of `XY` or `ParallelXY`?
> 
> 
> You reminded me of the existence of this:
> 
> https://github.com/rikkimax/DIPs/blob/master/DIPs/DIP1xxx-RC.md

My signature DIP (one of the many versions of it).

Current status: waiting on a dependency of named parameters before continuing.
July 27, 2019
On Saturday, 27 July 2019 at 09:38:20 UTC, Mike Franklin wrote:
> On Saturday, 27 July 2019 at 05:09:11 UTC, XavierAP wrote:
>
>>     interface IPrintable
>>     {
>>         string toString();
>>     }
>
> I like the idea of using interfaces, but I'm not sure how to implement such a thing for structs.  Is it just a compile-time contract?  How does it work at runtime when we call a function like `void foo(IPrintable p);` with an instance of `XY` or `ParallelXY`?

Indeed the options and their consequences have to be studied. In principle I would constrain it, again no virtual dispatch whatsoever, and keep the value semantics. We can take a look at how C# already does it. I think Go has a similar feature.

But imo it should imply polymorphism (e.g. in function parameter types) as you ask.

And it's not only at runtime, or rather the border line between compile time and run time can be different for each program. Because unlike classes, structs are statically instantiated, the examples you ask may be ver well evaluating at ct, e.g.

    enum XY p = { 1, 2 };
    enum s = p.toString();

But note also that interfaces in structs would be a separate feature/DIP from struct inheritance (from other structs, not interfaces).

And given the extensive preference in the current D crowd (and in Phobos) for templates, there's no big use case for structs implementating interfaces, as there is however imo for inheritance.

> Are you suggesting the body of `XY` simply be copied into `ParallelXY`?  I think that can already be done with template mixins.

Indeed I know you can implement these simple features building on the more complex (and macro-ish), but it shouldn't be done this way, and that was my point.

What I am suggesting is to implement new into the language the very simple inheritance that already exists for classes, or the same that C++ has for its RAII classes/structs.

An inherited type includes (contains, memory-wise) the base type. The additional members defined in the derived type declaration are aligned after the inherited ones. That's why the derived type can also be used anywhere in place of the base one (polymorphism).

Implementing this simple feature from template mixins does not guarantee this memory alignment. Plus imo it's wrong to build a brick out of houses.

Here you have an example I wrote with (macro-ish) template mixins, while it would vave been much better with (private) inheritance:

https://github.com/XavierAP/femd/blob/master/src/algebra/statics.d

Amd here's another example where inheritance would have been better than composition:

https://github.com/XavierAP/game-king/blob/master/source/sdl_help.d