www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Multiple alias this, what's the hold up?

reply Amex <Amex gmail.com> writes:
How many years has it been in limbo? 1? 2? 3? 5? 10?

What is the hold up?


Expression resolveAliasThis(Scope* sc, Expression e, bool gag = 
false)
{
     for (AggregateDeclaration ad = isAggregate(e.type); ad;)
     {
         if (ad.aliasthis)
         {
             uint olderrors = gag ? global.startGagging() : 0;
             Loc loc = e.loc;
             Type tthis = (e.op == TOK.type ? e.type : null);
             e = new DotIdExp(loc, e, ad.aliasthis.ident);
             e = e.expressionSemantic(sc);
             if (tthis && ad.aliasthis.needThis())
             {
                 if (e.op == TOK.variable)
                 {
                     if (auto fd = 
(cast(VarExp)e).var.isFuncDeclaration())
                     {
                         // 
https://issues.dlang.org/show_bug.cgi?id=13009
                         // Support better match for the 
overloaded alias this.
                         bool hasOverloads;
                         if (auto f = fd.overloadModMatch(loc, 
tthis, hasOverloads))
                         {
                             if (!hasOverloads)
                                 fd = f;     // use exact match
                             e = new VarExp(loc, fd, hasOverloads);
                             e.type = f.type;
                             e = new CallExp(loc, e);
                             goto L1;
                         }
                     }
                 }
                 /* non- property function is not called inside 
typeof(),
                  * so resolve it ahead.
                  */
                 {
                     int save = sc.intypeof;
                     sc.intypeof = 1; // bypass "need this" error 
check
                     e = resolveProperties(sc, e);
                     sc.intypeof = save;
                 }
             L1:
                 e = new TypeExp(loc, new TypeTypeof(loc, e));
                 e = e.expressionSemantic(sc);
             }
             e = resolveProperties(sc, e);
             if (gag && global.endGagging(olderrors))
                 e = null;
         }

         import dmd.dclass : ClassDeclaration;
         auto cd = ad.isClassDeclaration();
         if ((!e || !ad.aliasthis) && cd && cd.baseClass && 
cd.baseClass != ClassDeclaration.object)
         {
             ad = cd.baseClass;
             continue;
         }
         break;
     }
     return e;
}
Jun 15 2019
next sibling parent reply 12345swordy <alexanderheistermann gmail.com> writes:
On Saturday, 15 June 2019 at 10:12:46 UTC, Amex wrote:
 How many years has it been in limbo? 1? 2? 3? 5? 10?

 What is the hold up?
What the hold up is that walter thinks it is a bad idea to implement multiple alias this as he think it results in a multiple inheritance problem. There has been recent discussion regarding deprecating alias this.
Jun 15 2019
parent reply Jonathan Marler <johnnymarler gmail.com> writes:
On Saturday, 15 June 2019 at 23:30:09 UTC, 12345swordy wrote:
 On Saturday, 15 June 2019 at 10:12:46 UTC, Amex wrote:
 How many years has it been in limbo? 1? 2? 3? 5? 10?

 What is the hold up?
What the hold up is that walter thinks it is a bad idea to implement multiple alias this as he think it results in a multiple inheritance problem. There has been recent discussion regarding deprecating alias this.
Maybe we could add it as an optional feature enabled with a command-line option? I think there's a command line format for features like this "-feature=miltialias" or something. That way if there really are issues we could demonstrate them and remove the feature later, or if no issues are found it could be enabled by default.
Jun 15 2019
parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 16.06.19 03:04, Jonathan Marler wrote:
 On Saturday, 15 June 2019 at 23:30:09 UTC, 12345swordy wrote:
 On Saturday, 15 June 2019 at 10:12:46 UTC, Amex wrote:
 How many years has it been in limbo? 1? 2? 3? 5? 10?

 What is the hold up?
What the hold up is that walter thinks it is a bad idea to implement multiple alias this as he think it results in a multiple inheritance problem. There has been recent discussion regarding deprecating alias this.
Maybe we could add it as an optional feature enabled with a command-line option? I think there's a command line format for features like this "-feature=miltialias" or something. ...
That probably won't fly.
 That way if there really are issues we could demonstrate them and remove 
 the feature later, or if no issues are found it could be enabled by 
 default.
In terms of lookup, the issues with multiple alias this are the same as the issues with multiple import declarations. Implicit conversions could use the same lookup rules, but there would need to be a way to disambiguate. The code in the compiler that implements import declarations is unlikely to be easily reusable.
Jun 15 2019
next sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 6/15/2019 6:21 PM, Timon Gehr wrote:
 In terms of lookup, the issues with multiple alias this are the same as the 
 issues with multiple import declarations. Implicit conversions could use the 
 same lookup rules, but there would need to be a way to disambiguate. The code
in 
 the compiler that implements import declarations is unlikely to be easily
reusable.
Multiple alias this is multiple inheritance. Generally, if you find yourself wanting multiple inheritance, it's likely time to rethink the data structures.
Jun 15 2019
next sibling parent Jonathan Marler <johnnymarler gmail.com> writes:
On Sunday, 16 June 2019 at 06:08:54 UTC, Walter Bright wrote:
 On 6/15/2019 6:21 PM, Timon Gehr wrote:
 In terms of lookup, the issues with multiple alias this are 
 the same as the issues with multiple import declarations. 
 Implicit conversions could use the same lookup rules, but 
 there would need to be a way to disambiguate. The code in the 
 compiler that implements import declarations is unlikely to be 
 easily reusable.
Multiple alias this is multiple inheritance. Generally, if you find yourself wanting multiple inheritance, it's likely time to rethink the data structures.
There's not many cases where I've really needed/wanted multiple alias this. I do have one case where I thought it would be nice which I'll share for anyone interested. It was when I created the SentinelArray/SentinelPtr types. They represent arrays and pointers that are ended with a sentinel value. https://github.com/dragon-lang/mar/blob/master/src/mar/sentinel.d For example, a cstring would be a SentinelPtr!char. The reason for creating these types is to allow the type system to know whether or not a pointer already has a sentinel value. This is most useful when interfacing with C functions that take C strings. Declaring the string pointer as a SentinelPtr allows the type-system to both verify that all strings are null-terminated and allows the application to control when conversions from D-Strings to C-Strings occur rather than performing a conversion every time the function is called. To make these Sentinel types play well with the type system, I also supported using type modifiers like 'const' and 'immutable': SentinelPtr!char SentinelPtr!(const char) SentinelPtr!(immutable char) The reason for "alias this" would be to have them be implicitly convertible to both raw pointers for the mutable/immutable variants to be implicitly convertible to the const variant. So you could do things like: // // Implicitly convertible to raw pointer // void takesRawPointer(char* ptr); SentinelPtr!char p = ...; takesRawPointer(p); // // Mutable/Immutable implicitly convertible to const // void takeConstSentinelPtr(SentinelPtr!(const char) filename); SentinelPtr!char filename1 = ...; takeConstSentinelPtr(filename1); SentinelPtr!(immutable char) filename2 = ...; takeConstSentinelPtr(filename2); Since multiple alias this only supports one member I couldn't have both. So I chose to use alias this to convert mutable/immutable to const and raw pointer conversions requires an explicit member access (i.e. `mySentinelPtr.raw`). Having to call a member is not horrible, but having multiple alias this seems like it would be nicer. Anyway, thought it might be helpful to see a real use case. Of course, if anyone knows of a better solution to this problem I'm all ears :)
Jun 15 2019
prev sibling next sibling parent reply Mike Franklin <slavo5150 yahoo.com> writes:
On Sunday, 16 June 2019 at 06:08:54 UTC, Walter Bright wrote:

 Multiple alias this is multiple inheritance. Generally, if you 
 find yourself wanting multiple inheritance, it's likely time to 
 rethink the data structures.
If one should prefer composition to inheritance the language must provide the proper facilities to make composition just as convenient. I refer you to this StackOverflow question (https://stackoverflow.com/questions/255553/is-it-possible-to-im and aggregate implementations. The second comment to the question says it all:
 I find it annoying that C++ experts make statements like 
 "Prefer composition to inheritance" yet the language (C++ or 

Mike
Jun 16 2019
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 6/16/2019 2:33 AM, Mike Franklin wrote:
 I refer you to this StackOverflow question 
 (https://stackoverflow.com/questions/255553/is-it-possible-to-im
lement-mixins-in-c) 

 implementations.  The second comment to the question says it all:
 
 I find it annoying that C++ experts make statements like "Prefer composition 

 the "right thing".
Be careful about dismissing what experts say. Sometimes it takes many years of experience to understand that seemingly good ideas are not that good after all. I don't do use a lot of programming techniques I thought were way cool in my 20's, but now I understand are crap, like <cough cough>macros</cough cough>.
Jun 16 2019
parent Mike Franklin <slavo5150 yahoo.com> writes:
On Sunday, 16 June 2019 at 22:28:56 UTC, Walter Bright wrote:

 I refer you to this StackOverflow question 
 (https://stackoverflow.com/questions/255553/is-it-possible-to-im

and aggregate implementations.  The second comment to the question says it all:
 
 I find it annoying that C++ experts make statements like 
 "Prefer composition to inheritance" yet the language (C++ or 

Be careful about dismissing what experts say. Sometimes it takes many years of experience to understand that seemingly good ideas are not that good after all. I don't do use a lot of programming techniques I thought were way cool in my 20's, but now I understand are crap, like <cough cough>macros</cough cough>.
I think you may have misunderstood what that user and I are saying. We're not dismissing what the experts say, in fact we, for the most part, agree with them. What we're saying is that those experts, disingenuously, aren't acknowledging it. D has an opportunity, and is better positioned, to do better. If C++ style multiple inheritances is not the answer, what is? Eiffel's multiple inheritance? D's `alias this`? Design-by-introspection metaprogramming? "Suck it up, and get typing!"? Mike
Jun 16 2019
prev sibling next sibling parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 16.06.19 08:08, Walter Bright wrote:
 On 6/15/2019 6:21 PM, Timon Gehr wrote:
 In terms of lookup, the issues with multiple alias this are the same 
 as the issues with multiple import declarations. Implicit conversions 
 could use the same lookup rules, but there would need to be a way to 
 disambiguate. The code in the compiler that implements import 
 declarations is unlikely to be easily reusable.
Multiple alias this is multiple inheritance.
No. It's multiple imports. You have no vtable to populate, so you can just throw a compile-time error if some lookup is ambiguous and require explicit disambiguation, like for imports.
 Generally, if you find 
 yourself wanting multiple inheritance, it's likely time to rethink the 
 data structures.
Only if your programming language gets MI wrong. C++ gets MI wrong. This is how to do multiple inheritance: https://www.eiffel.org/doc/eiffel/ET-_Inheritance (Ignore the section about covariance. Eiffel gets that part totally wrong.)
Jun 16 2019
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 6/16/2019 7:39 AM, Timon Gehr wrote:
 On 16.06.19 08:08, Walter Bright wrote:
 Multiple alias this is multiple inheritance.
No. It's multiple imports.
D already has multiple imports with template mixins. If multiple imports is what people want, it's already there.
 Generally, if you find yourself wanting multiple inheritance, it's likely time 
 to rethink the data structures.
Only if your programming language gets MI wrong. C++ gets MI wrong. This is how to do multiple inheritance: https://www.eiffel.org/doc/eiffel/ET-_Inheritance (Ignore the section about covariance. Eiffel gets that part totally wrong.)
Designing a decent object is hard enough, and most everybody (including me) do a lousy job of it. When people start using MI, the mess becomes incredible. Maybe in another 20 years ago I'll get good enough to be able to write a sensible MI object.
Jun 16 2019
next sibling parent reply Adam D. Ruppe <destructionator gmail.com> writes:
On Sunday, 16 June 2019 at 22:14:19 UTC, Walter Bright wrote:
 On 6/16/2019 7:39 AM, Timon Gehr wrote:
 No. It's multiple imports.
D already has multiple imports with template mixins. If multiple imports is what people want, it's already there.
Actually, I'll disagree with both of you. I think alias this is really about enabling implicit conversion to the type of alias this. And multiple implicit conversion is obviously useful. Though speaking of template mixin, I think it would be kinda cool to be able to mixin a struct or maybe a .tupleof thingy; just treat a struct as if it was a mixin template.
Jun 16 2019
parent Timon Gehr <timon.gehr gmx.ch> writes:
On 17.06.19 00:28, Adam D. Ruppe wrote:
 On Sunday, 16 June 2019 at 22:14:19 UTC, Walter Bright wrote:
 On 6/16/2019 7:39 AM, Timon Gehr wrote:
 No. It's multiple imports.
D already has multiple imports with template mixins. If multiple imports is what people want, it's already there.
Actually, I'll disagree with both of you. I think alias this is really about enabling implicit conversion to the type of alias this. And multiple implicit conversion is obviously useful. ...
Sure, it does that too, but this doesn't really inform the design. (Furthermore, I think it is actually pretty annoying that those two aspects of `alias this` are mixed together into the same language feature). And anyway, right now, alias this is a bad mechanism for this because it does not allow introspection on the expected type to generate code that performs the conversion. If there was just general expected-return-type-based IFTI (instead of just for non-aliased template function literals), single alias this would suffice for your use case.
Jun 16 2019
prev sibling next sibling parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 17.06.19 00:14, Walter Bright wrote:
 On 6/16/2019 7:39 AM, Timon Gehr wrote:
 On 16.06.19 08:08, Walter Bright wrote:
 Multiple alias this is multiple inheritance.
No. It's multiple imports.
D already has multiple imports with template mixins. If multiple imports is what people want, it's already there. ...
No. Mixins and imports are not the same thing. E.g., this code is fine: import std.stdio; void main(){ writeln("hello world!"); } This code is horrible (it does not even compile): mixin(import("std/stdio.d")); void main(){ writeln("hello world!"); } (Whether the automated copy-pasting of code happens before or after parsing doesn't really matter.)
Jun 16 2019
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 6/16/2019 4:46 PM, Timon Gehr wrote:
 mixin(import("std/stdio.d"));
Template mixins are something else: https://dlang.org/spec/template-mixin.html
Jun 17 2019
parent Timon Gehr <timon.gehr gmx.ch> writes:
On 17.06.19 09:29, Walter Bright wrote:
 On 6/16/2019 4:46 PM, Timon Gehr wrote:
 mixin(import("std/stdio.d"));
Template mixins are something else: https://dlang.org/spec/template-mixin.html
In my answer I explicitly stated that for the purpose of my argument, mixing in commutes with parsing. There isn't an obvious way to turn a module into a mixin template, so it was easier to make my point with a string mixin. To elaborate on my previous preemptive strike against your complaint, from that page of the spec: "Unlike a template instantiation, a template mixin's body is evaluated within the scope where the mixin appears, not where the template declaration is defined." This is not how `alias this` works. I know that importing a scope is part of how the `mixin` template is implemented. What I am saying is `alias this` should use the same kind of lookup rules, but without the mixing in -- only the importing. PS: And anyhow, how ironic! :) - I know what template mixins are. I implemented [1] them in a D compiler frontend. I know that importing [2] the _newly generated_ scope is one step in the implementation. - In general, I know most of the language spec by heart. I also know about almost all aspects of D semantics that are missing or wrong in the language specification. [1] https://github.com/tgehr/d-compiler/blob/master/semantic.d#L3308 [2] https://github.com/tgehr/d-compiler/blob/master/semantic.d#L3348
Jun 17 2019
prev sibling parent reply Exil <Exil gmall.com> writes:
On Sunday, 16 June 2019 at 22:14:19 UTC, Walter Bright wrote:
 On 6/16/2019 7:39 AM, Timon Gehr wrote:
 On 16.06.19 08:08, Walter Bright wrote:
 Multiple alias this is multiple inheritance.
No. It's multiple imports.
D already has multiple imports with template mixins. If multiple imports is what people want, it's already there.
Isn't there an entire thread arguing for the inclusion of *single* inheritance. Not sure how you can say we have multiple inheritance without even having inheritance (for structs).
 Generally, if you find yourself wanting multiple inheritance, 
 it's likely time to rethink the data structures.
Only if your programming language gets MI wrong. C++ gets MI wrong. This is how to do multiple inheritance: https://www.eiffel.org/doc/eiffel/ET-_Inheritance (Ignore the section about covariance. Eiffel gets that part totally wrong.)
Designing a decent object is hard enough, and most everybody (including me) do a lousy job of it. When people start using MI, the mess becomes incredible. Maybe in another 20 years ago I'll get good enough to be able to write a sensible MI object.
I feel like without virtual functions it isn't really multiple inheritance. Alias this is just syntactic sugar so that you don't have to specify the variable to use it. Things like the diamond problem don't exist because you can't override functions in structs. If you have 2 structs and both of them have a struct A that is used with "alias this" and then you "alias this" on both those structs. Implicitly converting to A would be a compile time error. They are not related and the conversion is ambiguous between the two. I'd be fine with it simply being too complicated to implement, it can be. But saying it is the same thing as Multiple Inheritance, and that it shouldn't be implemented because it is multiple inheritance. That I don't agree with.
Jun 17 2019
parent reply user1234 <user1234 12.de> writes:
On Tuesday, 18 June 2019 at 00:58:58 UTC, Exil wrote:
 On Sunday, 16 June 2019 at 22:14:19 UTC, Walter Bright wrote:
 On 6/16/2019 7:39 AM, Timon Gehr wrote:
 On 16.06.19 08:08, Walter Bright wrote:
 Multiple alias this is multiple inheritance.
No. It's multiple imports.
D already has multiple imports with template mixins. If multiple imports is what people want, it's already there.
Isn't there an entire thread arguing for the inclusion of *single* inheritance. Not sure how you can say we have multiple inheritance without even having inheritance (for structs).
 Generally, if you find yourself wanting multiple 
 inheritance, it's likely time to rethink the data structures.
Only if your programming language gets MI wrong. C++ gets MI wrong. This is how to do multiple inheritance: https://www.eiffel.org/doc/eiffel/ET-_Inheritance (Ignore the section about covariance. Eiffel gets that part totally wrong.)
Designing a decent object is hard enough, and most everybody (including me) do a lousy job of it. When people start using MI, the mess becomes incredible. Maybe in another 20 years ago I'll get good enough to be able to write a sensible MI object.
I feel like without virtual functions it isn't really multiple inheritance. Alias this is just syntactic sugar so that you don't have to specify the variable to use it. Things like the diamond problem don't exist because you can't override functions in structs.
The diamond problem in theory is possible but the compiler implementation would error with recursion when making type semantic.
Jun 18 2019
parent Exil <Exil gmall.com> writes:
On Tuesday, 18 June 2019 at 23:33:12 UTC, user1234 wrote:
 On Tuesday, 18 June 2019 at 00:58:58 UTC, Exil wrote:
 On Sunday, 16 June 2019 at 22:14:19 UTC, Walter Bright wrote:
 On 6/16/2019 7:39 AM, Timon Gehr wrote:
 On 16.06.19 08:08, Walter Bright wrote:
 Multiple alias this is multiple inheritance.
No. It's multiple imports.
D already has multiple imports with template mixins. If multiple imports is what people want, it's already there.
Isn't there an entire thread arguing for the inclusion of *single* inheritance. Not sure how you can say we have multiple inheritance without even having inheritance (for structs).
 Generally, if you find yourself wanting multiple 
 inheritance, it's likely time to rethink the data 
 structures.
Only if your programming language gets MI wrong. C++ gets MI wrong. This is how to do multiple inheritance: https://www.eiffel.org/doc/eiffel/ET-_Inheritance (Ignore the section about covariance. Eiffel gets that part totally wrong.)
Designing a decent object is hard enough, and most everybody (including me) do a lousy job of it. When people start using MI, the mess becomes incredible. Maybe in another 20 years ago I'll get good enough to be able to write a sensible MI object.
I feel like without virtual functions it isn't really multiple inheritance. Alias this is just syntactic sugar so that you don't have to specify the variable to use it. Things like the diamond problem don't exist because you can't override functions in structs.
The diamond problem in theory is possible but the compiler implementation would error with recursion when making type semantic.
It's not possible, that's why the compiler would give an error. It wouldn't even be recursion, it would see both available. That's if it is even implemented that way. With classes the only "alias this" that are checked are of the type being used. It doesn't check the "alias this" of the base class. https://run.dlang.io/is/EqliF5
Jun 18 2019
prev sibling next sibling parent Amex <Amex gmail.com> writes:
On Sunday, 16 June 2019 at 06:08:54 UTC, Walter Bright wrote:
 On 6/15/2019 6:21 PM, Timon Gehr wrote:
 In terms of lookup, the issues with multiple alias this are 
 the same as the issues with multiple import declarations. 
 Implicit conversions could use the same lookup rules, but 
 there would need to be a way to disambiguate. The code in the 
 compiler that implements import declarations is unlikely to be 
 easily reusable.
Multiple alias this is multiple inheritance. Generally, if you find yourself wanting multiple inheritance, it's likely time to rethink the data structures.
This is not true! Alias this is does not use inheritance at all. There is no vtable for alias this. It's purely compile time. It's purely to simplify dispatching. https://dlang.org/spec/class.html#AliasThis Says nothing about inheritance. There is no diamond problem so I really have no idea what you are talking about. Alias this is entirely for convinces and is only compile time. The reason why the diamond problem is an issue is because it can occur without the compiler being able to determine that is is a problem(such as with plugins). With alias this, the compiler always can determine what is going. I think you are mistaken here. I could be wrong. Do you have proof of what you claim? struct X { int q; alias q this; } Where is the inherence in this code? as far as the docs they simply say that we can treat any instance x of X as if we used x.q. Hence, instead of having to write x.q all over the place we can write x. How can this ever create a diamond problem? And if it did how would that not be caught at compile time?
Jun 16 2019
prev sibling next sibling parent Guillaume Piolat <contact+spam spam.org> writes:
On Sunday, 16 June 2019 at 06:08:54 UTC, Walter Bright wrote:
 On 6/15/2019 6:21 PM, Timon Gehr wrote:
 In terms of lookup, the issues with multiple alias this are 
 the same as the issues with multiple import declarations. 
 Implicit conversions could use the same lookup rules, but 
 there would need to be a way to disambiguate. The code in the 
 compiler that implements import declarations is unlikely to be 
 easily reusable.
Multiple alias this is multiple inheritance. Generally, if you find yourself wanting multiple inheritance, it's likely time to rethink the data structures.
+1 And in D I've "needed" multiple inheritance exactly once, so I wonder what is the use case for multiple alias this...
Jun 16 2019
prev sibling next sibling parent reply Ethan <gooberman gmail.com> writes:
On Sunday, 16 June 2019 at 06:08:54 UTC, Walter Bright wrote:
 Multiple alias this is multiple inheritance. Generally, if you 
 find yourself wanting multiple inheritance, it's likely time to 
 rethink the data structures.
I'm going to voice up for the "not generally" case. Other people have made the point about casting to the internal type, and I've certainly used that to simulate value-type inheritance for C++ interop (see the talks I did at DConf 2016 and 2017; and more recently, Manu requesting struct inheritance for this very purpose). But that's not the point I want to make. The games industry was slow to adopt object-oriented programming solely because of the performance implications in compilers at the time. It was really only in the Playstation 2 era that C++ became the de facto standard. And just as quickly, we started realising object oriented programming wasn't all it was cracked up to be. One example I always bring up here is a PS2 game that Manu and I are credited on. We had friendly characters that would stand around and respond to the player character whenever interacted with, usually to give out missions and rewards. The hierarchy to get this working was something like: * MKProp - Base level engine functionality for game objects. * KDProp - An extended library that added common game functionality that fell outside of pure engine code. * KDPropEx - An extension that introduced a component object system. * DynamicProp - The first level in the hierarchy actually in game logic, included collision objects for dynamic simulation purposes. * Character - Now with animation and a few other things that general humanoid objects would use. * Friend - As opposed to the Enemy object, a bunch of routines for friendly characters and making sure there was no way to actually kill them for example. * IdleFriend - Turns almost everything about a Friend/Character/DynamicProp/KDPropEx/KDProp/MKProp off solely to make a static friendly character that you could talk to. ...yeah. That is bonkers. The solution we've been settling on for a while is already hinted to above. Component object systems. The idea being that we take discrete chunks of logic and encapsulate them in one object. So a visual mesh is one component. Collision. Animation systems. So on and so forth. You define an object by what it uses, not where it fits best in an object hierarchy. Doing it this way is easier to maintain and heavily promotes code re-usability. It also means you define new game object types with data rather than with code. But there are some costs. Your game object stops being something you can cast up and down a hierarchy, instead you have to query objects for the existence of a component that you're interested in. That's a runtime cost, usually a map lookup of some sort. Perhaps you can already see where I'm going here. Engine and Unity all suffer from the same problem - they can't do the compile time tricks we can do in D, and as such you are always left with resolving components via a runtime lookup. All the compile time safety we can introduce in D really isn't possible without doing separate pre-processing. But a D system? It could look at the data definitions and generate code objects for any given component layout at compile time. The easiest way to implement that? Embed them all within a containing struct. Multiple alias this in this case would make exposing functionality and variables contained within each component a trivial matter. Without multiple alias this, you have to do exactly what I do with Binderoo C++ binding and parse each relevant object to generate wrapper functions for it. Up goes the compile time. (And related - code safety becomes template constraints checking exactly how you check if a range is a forward range etc.) Similarly to this - the behaviors system I talked about in my DConf talk this year that provided a decent facsimile for partial one that I intend on putting in to widespread use. It's 100% habit for me at this point in time to write discrete code objects and combine them outside of traditional object oriented programming methodology. The implication here also is that component-based programming is not a method that the games industry is going to drop any time soon. If you're doing console game development, you need to be familiar with how to use components. And with D, we can start making that seamless and performant.
Jun 17 2019
parent Olivier FAURE <couteaubleu gmail.com> writes:
On Monday, 17 June 2019 at 17:41:07 UTC, Ethan wrote:
 The implication here also is that component-based programming 
 is not a method that the games industry is going to drop any 
 time soon. If you're doing console game development, you need 
 to be familiar with how to use components.
I agree with you that D has great potential as tool to write an Entity-Component-System architecture better than existing languages (for instance, it can swap arrays-of-structs with structs-of-arrays pretty seamlessly), but I don't follow how `alias this` is necessary or even helpful for ECS? All use cases I've seen could be handled idiomatically with `static foreach`, `static if` and `__traits(hasMember, ...)`. Functions meant for an idiomatic ECS framework would look like: needs_components(Health, DamageToken) optional_components(ArmorSystem) needs_tags("!immortal") void system_applyDamage(int entityId, ref Health, ref DamageToken, ArmorSystem*) { ... } No recompilation needed, expresses exactly what it does. I don't think you need `alias this` at all.
Jun 18 2019
prev sibling parent reply =?UTF-8?Q?Ali_=c3=87ehreli?= <acehreli yahoo.com> writes:
On 06/15/2019 11:08 PM, Walter Bright wrote:
 On 6/15/2019 6:21 PM, Timon Gehr wrote:
 In terms of lookup, the issues with multiple alias this are the same 
 as the issues with multiple import declarations. Implicit conversions 
 could use the same lookup rules, but there would need to be a way to 
 disambiguate. The code in the compiler that implements import 
 declarations is unlikely to be easily reusable.
Multiple alias this is multiple inheritance. Generally, if you find yourself wanting multiple inheritance, it's likely time to rethink the data structures.
Does this mean multiple alias this will never happen? I would love to remove a section in my book that was added in the hopes of seeing this feature "any day now". :) I like the example I came up with though: A TeachingAssistant class that can appear in a Student context as well as in a Teacher context. Ali
Jun 18 2019
parent reply Jonathan M Davis <newsgroup.d jmdavisprog.com> writes:
On Tuesday, June 18, 2019 4:08:49 PM MDT Ali ehreli via Digitalmars-d 
wrote:
 On 06/15/2019 11:08 PM, Walter Bright wrote:
 On 6/15/2019 6:21 PM, Timon Gehr wrote:
 In terms of lookup, the issues with multiple alias this are the same
 as the issues with multiple import declarations. Implicit conversions
 could use the same lookup rules, but there would need to be a way to
 disambiguate. The code in the compiler that implements import
 declarations is unlikely to be easily reusable.
Multiple alias this is multiple inheritance. Generally, if you find yourself wanting multiple inheritance, it's likely time to rethink the data structures.
Does this mean multiple alias this will never happen? I would love to remove a section in my book that was added in the hopes of seeing this feature "any day now". :) I like the example I came up with though: A TeachingAssistant class that can appear in a Student context as well as in a Teacher context.
It definitely looks like a DIP would be required for multiple alias this-es to become a thing, and whatever was in the DIP would have to convince Walter that it doesn't have the problems that multiple inheritance has. Certainly, it's not simply a matter of someone needing to implement it, which is often how the issue is portrayed, though a solid implementation could help convince Walter. I expect that it's perfectly safe to remove mentioning multiple alias this-es from your book and that it would give a far more accurate representation of the state of D. Acting like it's just a matter of time before multiple alias this-es get added to D would be giving folks the wrong idea with how things stand. And if someone actually comes up with a proposal that convinces Walter, it's not like it would be hard to grab what you had and re-add it with any necessary changes (at least if you have your book in source control like I would think you would). Based on some of the discussions on the topic, it seems more likely to me that alias this will be replaced with some other feature than we'll ever get the ability to have multiple alias this-es on the same type. - Jonathan M Davis
Jun 18 2019
next sibling parent reply Mike Franklin <slavo5150 yahoo.com> writes:
On Tuesday, 18 June 2019 at 22:51:51 UTC, Jonathan M Davis wrote:

 It definitely looks like a DIP would be required for multiple 
 alias this-es to become a thing, and whatever was in the DIP 
 would have to convince Walter that it doesn't have the problems 
 that multiple inheritance has.
DIP66 (https://wiki.dlang.org/DIP66) was already created and approved. Did you have something else in mind? Mike
Jun 18 2019
parent reply Jonathan M Davis <newsgroup.d jmdavisprog.com> writes:
On Tuesday, June 18, 2019 10:09:24 PM MDT Mike Franklin via Digitalmars-d 
wrote:
 On Tuesday, 18 June 2019 at 22:51:51 UTC, Jonathan M Davis wrote:
 It definitely looks like a DIP would be required for multiple
 alias this-es to become a thing, and whatever was in the DIP
 would have to convince Walter that it doesn't have the problems
 that multiple inheritance has.
DIP66 (https://wiki.dlang.org/DIP66) was already created and approved. Did you have something else in mind?
Given Walter's more recent statements on the matter, it doesn't sound like it's approved anymore. He's repeatedly compared having multiple alias this-es to multiple inheritance and expressed that it's a bad idea. - Jonathan M Davis
Jun 18 2019
parent reply Jonathan Marler <johnnymarler gmail.com> writes:
On Wednesday, 19 June 2019 at 05:53:42 UTC, Jonathan M Davis 
wrote:
 On Tuesday, June 18, 2019 10:09:24 PM MDT Mike Franklin via 
 Digitalmars-d wrote:
 On Tuesday, 18 June 2019 at 22:51:51 UTC, Jonathan M Davis 
 wrote:
 It definitely looks like a DIP would be required for 
 multiple alias this-es to become a thing, and whatever was 
 in the DIP would have to convince Walter that it doesn't 
 have the problems that multiple inheritance has.
DIP66 (https://wiki.dlang.org/DIP66) was already created and approved. Did you have something else in mind?
Given Walter's more recent statements on the matter, it doesn't sound like it's approved anymore. He's repeatedly compared having multiple alias this-es to multiple inheritance and expressed that it's a bad idea. - Jonathan M Davis
It's fair to say that multiple alias this and multiple inheritance have similarities, but some have argued that the "bad parts" of multiple inheritance don't apply to 'alias this' (i.e. the "Diamond Problem"). I'm hoping Walter will reveal what problems he claims apply to both as I haven't seen anyone else point them out yet.
Jun 18 2019
parent aliak <something something.com> writes:
On Wednesday, 19 June 2019 at 06:05:31 UTC, Jonathan Marler wrote:
 On Wednesday, 19 June 2019 at 05:53:42 UTC, Jonathan M Davis 
 wrote:
 On Tuesday, June 18, 2019 10:09:24 PM MDT Mike Franklin via 
 Digitalmars-d wrote:
 On Tuesday, 18 June 2019 at 22:51:51 UTC, Jonathan M Davis 
 wrote:
 It definitely looks like a DIP would be required for 
 multiple alias this-es to become a thing, and whatever was 
 in the DIP would have to convince Walter that it doesn't 
 have the problems that multiple inheritance has.
DIP66 (https://wiki.dlang.org/DIP66) was already created and approved. Did you have something else in mind?
Given Walter's more recent statements on the matter, it doesn't sound like it's approved anymore. He's repeatedly compared having multiple alias this-es to multiple inheritance and expressed that it's a bad idea. - Jonathan M Davis
It's fair to say that multiple alias this and multiple inheritance have similarities, but some have argued that the "bad parts" of multiple inheritance don't apply to 'alias this' (i.e. the "Diamond Problem"). I'm hoping Walter will reveal what problems he claims apply to both as I haven't seen anyone else point them out yet.
That's not to say that alias this itself doesn't have its design problems (i.e. searchability is hard - but that can be fixed by changing the syntax a bit), and there's this gotcha: class A { int i; void f() { writeln(i); } } class B { A a; alias a this; } void main() { auto b = new B(); if (b !is null) { b.f; // Wait what? - proceed to spend days going crazy. } } And then you have at least the problem that any implicit behaviour comes with - traceability. Question: can the compiler issue an Error instead of segfaulting when directing flow to a reference type alias this member? It would make bug tracing the gotcha above a million times more easy. But I am also curious about what the overlapping problems with MI are: With regards to implementation details, the diamond problem errors out, and the layout problem is defined by member layout, which is also solved. And implicitness is desirable in some cases. Also remember, it's "prefer" composition over inheritance. Not "never use". As always, there's a balance and it depends on the situation.
Jun 19 2019
prev sibling parent reply Les De Ridder <les lesderid.net> writes:
On Tuesday, 18 June 2019 at 22:51:51 UTC, Jonathan M Davis wrote:
 [...]

 I expect that it's perfectly safe to remove mentioning multiple 
 alias this-es from your book and that it would give a far more 
 accurate representation of the state of D. Acting like it's 
 just a matter of time before multiple alias this-es get added 
 to D would be giving folks the wrong idea with how things 
 stand. And if someone actually comes up with a proposal that 
 convinces Walter, it's not like it would be hard to grab what 
 you had and re-add it with any necessary changes (at least if 
 you have your book in source control like I would think you 
 would).

 [...]
If that's indeed the case it should probably be removed from the spec[1] as well. [1] https://dlang.org/spec/class.html#alias-this (subsection 7)
Jun 19 2019
parent Jonathan M Davis <newsgroup.d jmdavisprog.com> writes:
On Wednesday, June 19, 2019 1:29:40 AM MDT Les De Ridder via Digitalmars-d 
wrote:
 On Tuesday, 18 June 2019 at 22:51:51 UTC, Jonathan M Davis wrote:
 [...]

 I expect that it's perfectly safe to remove mentioning multiple
 alias this-es from your book and that it would give a far more
 accurate representation of the state of D. Acting like it's
 just a matter of time before multiple alias this-es get added
 to D would be giving folks the wrong idea with how things
 stand. And if someone actually comes up with a proposal that
 convinces Walter, it's not like it would be hard to grab what
 you had and re-add it with any necessary changes (at least if
 you have your book in source control like I would think you
 would).

 [...]
If that's indeed the case it should probably be removed from the spec[1] as well. [1] https://dlang.org/spec/class.html#alias-this (subsection 7)
IMHO, regardless of whether we intend to add the ability to have multiple alias this-es, the spec really shouldn't say that they're a thing when they're not actually implemented - even if it then follows that up by saying that they're not currently implemented like it does right now. - Jonathan M Davis
Jun 19 2019
prev sibling parent reply Jonathan Marler <johnnymarler gmail.com> writes:
On Sunday, 16 June 2019 at 01:21:16 UTC, Timon Gehr wrote:
 On 16.06.19 03:04, Jonathan Marler wrote:
 On Saturday, 15 June 2019 at 23:30:09 UTC, 12345swordy wrote:
 On Saturday, 15 June 2019 at 10:12:46 UTC, Amex wrote:
 How many years has it been in limbo? 1? 2? 3? 5? 10?

 What is the hold up?
What the hold up is that walter thinks it is a bad idea to implement multiple alias this as he think it results in a multiple inheritance problem. There has been recent discussion regarding deprecating alias this.
Maybe we could add it as an optional feature enabled with a command-line option? I think there's a command line format for features like this "-feature=miltialias" or something. ...
That probably won't fly.
 That way if there really are issues we could demonstrate them 
 and remove the feature later, or if no issues are found it 
 could be enabled by default.
In terms of lookup, the issues with multiple alias this are the same as the issues with multiple import declarations. Implicit conversions could use the same lookup rules, but there would need to be a way to disambiguate. The code in the compiler that implements import declarations is unlikely to be easily reusable.
Having a hard time trying to figure out what you mean here. I'm not sure what you mean by "multiple import declarations". Is this what you mean? import std.stdio; import std.stdio; Or maybe this? import std.stdio; void foo() { import std.stdio; } Then you said "Implicit conversions could use the same lookup rules", but I'm not sure what you're saying there either. Maybe if I understood what you meant my "import declarations" then it would make sense? Sorry if I just missed something.
Jun 15 2019
parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 16.06.19 08:19, Jonathan Marler wrote:
 On Sunday, 16 June 2019 at 01:21:16 UTC, Timon Gehr wrote:
 On 16.06.19 03:04, Jonathan Marler wrote:
 On Saturday, 15 June 2019 at 23:30:09 UTC, 12345swordy wrote:
 On Saturday, 15 June 2019 at 10:12:46 UTC, Amex wrote:
 How many years has it been in limbo? 1? 2? 3? 5? 10?

 What is the hold up?
What the hold up is that walter thinks it is a bad idea to implement multiple alias this as he think it results in a multiple inheritance problem. There has been recent discussion regarding deprecating alias this.
Maybe we could add it as an optional feature enabled with a command-line option? I think there's a command line format for features like this "-feature=miltialias" or something. ...
That probably won't fly.
 That way if there really are issues we could demonstrate them and 
 remove the feature later, or if no issues are found it could be 
 enabled by default.
In terms of lookup, the issues with multiple alias this are the same as the issues with multiple import declarations. Implicit conversions could use the same lookup rules, but there would need to be a way to disambiguate. The code in the compiler that implements import declarations is unlikely to be easily reusable.
Having a hard time trying to figure out what you mean here.  I'm not sure what you mean by "multiple import declarations".  Is this what you mean? import std.stdio; import std.stdio; Or maybe this? import std.stdio; void foo() {     import std.stdio; } Then you said "Implicit conversions could use the same lookup rules", but I'm not sure what you're saying there either.  Maybe if I understood what you meant my "import declarations" then it would make sense? ...
Probably. What I mean is multiple imports of different modules: import std.file; import std.stdio; void main(){ write("hello","world"); // error: ambiguous } This is the same situation as: struct S{ void write(T...)(string file,T args){ ... } } struct T{ void write(T...)(T args){ ... } } struct U{ S s; T t; alias s this; alias t this; } void main(){ U u; u.write("hello","world"); // error: ambiguous } Basically any complaint against multiple `alias this` can be turned into a complaint against multiple imports, and all the solutions already exist in D's module system.
Jun 16 2019
parent reply Jonathan Marler <johnnymarler gmail.com> writes:
On Sunday, 16 June 2019 at 14:23:37 UTC, Timon Gehr wrote:
 On 16.06.19 08:19, Jonathan Marler wrote:
 On Sunday, 16 June 2019 at 01:21:16 UTC, Timon Gehr wrote:
 On 16.06.19 03:04, Jonathan Marler wrote:
 On Saturday, 15 June 2019 at 23:30:09 UTC, 12345swordy wrote:
 [...]
Maybe we could add it as an optional feature enabled with a command-line option? I think there's a command line format for features like this "-feature=miltialias" or something. ...
That probably won't fly.
 That way if there really are issues we could demonstrate 
 them and remove the feature later, or if no issues are found 
 it could be enabled by default.
In terms of lookup, the issues with multiple alias this are the same as the issues with multiple import declarations. Implicit conversions could use the same lookup rules, but there would need to be a way to disambiguate. The code in the compiler that implements import declarations is unlikely to be easily reusable.
Having a hard time trying to figure out what you mean here.  I'm not sure what you mean by "multiple import declarations".  Is this what you mean? import std.stdio; import std.stdio; Or maybe this? import std.stdio; void foo() {     import std.stdio; } Then you said "Implicit conversions could use the same lookup rules", but I'm not sure what you're saying there either.  Maybe if I understood what you meant my "import declarations" then it would make sense? ...
Probably. What I mean is multiple imports of different modules: import std.file; import std.stdio; void main(){ write("hello","world"); // error: ambiguous } This is the same situation as: struct S{ void write(T...)(string file,T args){ ... } } struct T{ void write(T...)(T args){ ... } } struct U{ S s; T t; alias s this; alias t this; } void main(){ U u; u.write("hello","world"); // error: ambiguous } Basically any complaint against multiple `alias this` can be turned into a complaint against multiple imports, and all the solutions already exist in D's module system.
Now I gotcha. One idea is to allow multiple alias this to use a search order, i.e. struct Foo { Bar bar; Baz baz; alias bar, baz this; // search bar, then baz } Foo foo; foo.func(); In this case it would try Bar first and fallback to baz. Of course, you could also just make it an error if you have multiple resolutions, which is what I think dmd does with multiple import matches. In any case, I don't think it matters much as these cases would be fairly uncommon. If you have a conflict, you can explicitly select one or the other (foo.bar.func() or foo.baz.func()).
Jun 16 2019
parent aliak <something something.com> writes:
On Sunday, 16 June 2019 at 18:25:28 UTC, Jonathan Marler wrote:
 Of course, you could also just make it an error if you have 
 multiple resolutions, which is what I think dmd does with 
 multiple import matches.  In any case, I don't think it matters 
 much as these cases would be fairly uncommon.  If you have a 
 conflict, you can explicitly select one or the other 
 (foo.bar.func() or foo.baz.func()).
That reminded me of private symbols that are publicly aliased. Currently this is not possible: struct S { private int a; public alias a this; } But I vaguely remember talk about implementing this. Tried to find a bug report but couldn't. Has there been discussion on allowing this or why not to allow it?
Jun 16 2019
prev sibling parent reply Mike Franklin <slavo5150 yahoo.com> writes:
On Saturday, 15 June 2019 at 10:12:46 UTC, Amex wrote:
 How many years has it been in limbo? 1? 2? 3? 5? 10?

 What is the hold up?
DIP66 is in need of champion. Do you wish to adopt https://github.com/dlang/dmd/pull/8378 and see it across the finish line? But I'm curious. Is there anything that `alias this` can do that can't be replicated with a mataprogramming library? Contrived, naive, very incomplete illustration: ``` import std.stdio; import std.traits; template AliasThis(alias f) { static foreach(m; __traits(allMembers, typeof(f))) { mixin( ReturnType!(__traits(getMember, typeof(f), m)).stringof ~ " " ~ m ~ "()" ~ "{" ~ __traits(identifier, f) ~ "." ~ m ~ "(); }" ); } } struct Base { void print() { writeln("Base.print"); } void print2() { writeln("Base.print2"); } } struct Base2 { void print3() { writeln("Base2.print3"); } void print4() { writeln("Base2.print4"); } } struct Derived { Base base; Base2 base2; mixin AliasThis!(base); mixin AliasThis!(base2); } void main() { Derived d; d.print(); d.print2(); d.print3(); d.print4(); } ``` Mike
Jun 16 2019
parent reply Adam D. Ruppe <destructionator gmail.com> writes:
On Sunday, 16 June 2019 at 09:26:21 UTC, Mike Franklin wrote:
 Contrived, naive, very incomplete illustration:

     static foreach(m; __traits(allMembers, typeof(f)))
     {
         mixin(
             ReturnType!(__traits(getMember, typeof(f), 
 m)).stringof
             ~ " " ~ m ~ "()"
             ~ "{" ~ __traits(identifier, f) ~ "." ~ m ~ "(); }"
         );
     }
It has kinda become my thing to comment on this whenever I can, but that code is needlessly hideous. 1) never use .stringof to feed back to the compiler. 2) ensure all newlines inside mixin() are also inside quotes, including the one immediately after the (. 3) (almost) never use concatenation to get a member Following those three rules simplifies that code to: static foreach(m; __traits(allMembers, typeof(f))) { mixin(" ReturnType!(__traits(getMember, typeof(f), m)) " ~ m ~ "() {__traits(getMember, f, m)(); }" ); } Notice the only thing concatenated is the name of the function now. So much simpler looking code, and it even works across module boundaries now. The reasons behind each rule: 1) stringof breaks if there is another matching name in scope, or if the name in question is not in scope at all (imagine a type from a user module passed to a different library module) 2) compiler error messages from inside the mixin may have misaligned line numbers if this is broken and of course, concat is ugly! Aside from formatting, you can also go a step further in simplification and remove that std.traits entirely with an auto function: static foreach(m; __traits(allMembers, typeof(f))) { mixin(" auto " ~ m ~ "() { return __traits(getMember, f, m)(); }" ); } auto functions aren't *exactly* the same... but there's several advantages here, including simpler code for return value, obviously, but also it will now inherit qualifiers from the wrapped function like nogc, pure, etc., thanks to inference rules.
Jun 17 2019
parent reply Mike Franklin <slavo5150 yahoo.com> writes:
On Monday, 17 June 2019 at 13:13:07 UTC, Adam D. Ruppe wrote:
 On Sunday, 16 June 2019 at 09:26:21 UTC, Mike Franklin wrote:
 Contrived, naive, very incomplete illustration:

     static foreach(m; __traits(allMembers, typeof(f)))
     {
         mixin(
             ReturnType!(__traits(getMember, typeof(f), 
 m)).stringof
             ~ " " ~ m ~ "()"
             ~ "{" ~ __traits(identifier, f) ~ "." ~ m ~ "(); }"
         );
     }
It has kinda become my thing to comment on this whenever I can, but that code is needlessly hideous.
I know and thank you for posting improvements, but it was just an illustration to convey that there may be a preferred path forward for multiple alias this: implement it in the library. So far I've only been able to find one `alias this` characteristic that can't be implemented in the library: ``` struct S { int i; void opAssign(int v) { i = v; } } void main() { S s; s = 1; int i = s; // No way to make this work in the library. We need `opAssignRight`. } ``` I think if we had an `opAssignRight` feature (with friends) we could move the entire implementation of `alias this` to the library. It would probably be a few hundred lines, but probably less than what it takes to implement in the compiler. We could even lower the `alias field this;` expression to `mixin AliasThis!(field);` so the user wouldn't know anything happened, assuming of course that the implementation of `AliasThis` was correct. I believe there have been 3 different PRs from the DIP66 author in the past few years attempting to implement multiple alias this, and none of them have been merged. Now there's talk that multiple alias this shouldn't ever be implemented. It seems to me the path forward is a pure library implementation. And, it would be nice to delete the hundreds, if not thousands, of lines of code needed to implement `alias this` in the compiler, along with all of the bugs that accompany it. Mike
Jun 17 2019
next sibling parent Jonathan Marler <johnnymarler gmail.com> writes:
On Monday, 17 June 2019 at 13:48:45 UTC, Mike Franklin wrote:
 On Monday, 17 June 2019 at 13:13:07 UTC, Adam D. Ruppe wrote:
 [...]
I know and thank you for posting improvements, but it was just an illustration to convey that there may be a preferred path forward for multiple alias this: implement it in the library. [...]
+1 to discuss opAssignRight That would solve my sentinel module problem.
Jun 17 2019
prev sibling next sibling parent reply user1234 <user1234 12.de> writes:
On Monday, 17 June 2019 at 13:48:45 UTC, Mike Franklin wrote:
 I think if we had an `opAssignRight` feature (with friends) we 
 could move the entire implementation of `alias this` to the 
 library. [...]
 Mike
At first glance opAssignRight is a really **brilliant** idea 👍. Why do you think that variants would be required ? i += s would work with the single op overload. Maybe it would more be something like T opExtractRight(T){}, with T saying what type is involved in the operation int i = s rewritten as int i = s.opExtractRight!int(); i += s rewritten as i += s.opExtractRight!int();
Jun 17 2019
parent reply rikki cattermole <rikki cattermole.co.nz> writes:
On 18/06/2019 3:58 AM, user1234 wrote:
 On Monday, 17 June 2019 at 13:48:45 UTC, Mike Franklin wrote:
 I think if we had an `opAssignRight` feature (with friends) we could 
 move the entire implementation of `alias this` to the library. [...]
 Mike
At first glance opAssignRight is a really **brilliant** idea 👍. Why do you think that variants would be required ? i += s would work with the single op overload. Maybe it would more be something like T opExtractRight(T){}, with T saying what type is involved in the operation int i = s  rewritten as  int i = s.opExtractRight!int(); i += s     rewritten as  i += s.opExtractRight!int();
Oh I like this. This way it doesn't fight the other operator overloads and can be used (with them) only if they fail as-is.
Jun 17 2019
next sibling parent reply user1234 <user1234 12.de> writes:
On Monday, 17 June 2019 at 16:13:07 UTC, rikki cattermole wrote:
 On 18/06/2019 3:58 AM, user1234 wrote:
 On Monday, 17 June 2019 at 13:48:45 UTC, Mike Franklin wrote:
 I think if we had an `opAssignRight` feature (with friends) 
 we could move the entire implementation of `alias this` to 
 the library. [...]
 Mike
At first glance opAssignRight is a really **brilliant** idea 👍. Why do you think that variants would be required ? i += s would work with the single op overload. Maybe it would more be something like T opExtractRight(T){}, with T saying what type is involved in the operation int i = s  rewritten as  int i = s.opExtractRight!int(); i += s     rewritten as  i += s.opExtractRight!int();
Oh I like this. This way it doesn't fight the other operator overloads and can be used (with them) only if they fail as-is.
It looks very much like "opCast" actually and a better named is "opImplicitConv" because right now the error message for Mike's little example says "cannot impliclty convert...".
Jun 17 2019
parent reply rikki cattermole <rikki cattermole.co.nz> writes:
On 18/06/2019 4:18 AM, user1234 wrote:
 It looks very much like "opCast" actually and a better named  is 
 "opImplicitConv"
 because right now the error message for Mike's little example says 
 "cannot impliclty convert...".
I thought about opCast as well, and it does look like it. But its not opCast. With regards to implicit casting, I don't think it is it. Implicit casting would be used in many more situations (e.g. return statements and function arguments). There is quite some push back against those use cases.
Jun 17 2019
parent reply user1234 <user1234 12.de> writes:
On Monday, 17 June 2019 at 16:27:59 UTC, rikki cattermole wrote:
 On 18/06/2019 4:18 AM, user1234 wrote:
 It looks very much like "opCast" actually and a better named  
 is "opImplicitConv"
 because right now the error message for Mike's little example 
 says "cannot impliclty convert...".
I thought about opCast as well, and it does look like it. But its not opCast. With regards to implicit casting, I don't think it is it. Implicit casting would be used in many more situations (e.g. return statements and function arguments). There is quite some push back against those use cases.
Semantics to call this possibly new operator must be well defined -> DIP
Jun 17 2019
parent Mike Franklin <slavo5150 yahoo.com> writes:
On Monday, 17 June 2019 at 17:39:54 UTC, user1234 wrote:

 Semantics to call this possibly new operator must be well 
 defined -> DIP
Indeed.
Jun 17 2019
prev sibling parent Basile B. <b2.temp gmx.com> writes:
On Monday, 17 June 2019 at 16:13:07 UTC, rikki cattermole wrote:
 On 18/06/2019 3:58 AM, user1234 wrote:
 On Monday, 17 June 2019 at 13:48:45 UTC, Mike Franklin wrote:
 I think if we had an `opAssignRight` feature (with friends) 
 we could move the entire implementation of `alias this` to 
 the library. [...]
 Mike
At first glance opAssignRight is a really **brilliant** idea 👍. Why do you think that variants would be required ? i += s would work with the single op overload. Maybe it would more be something like T opExtractRight(T){}, with T saying what type is involved in the operation int i = s  rewritten as  int i = s.opExtractRight!int(); i += s     rewritten as  i += s.opExtractRight!int();
Oh I like this. This way it doesn't fight the other operator overloads and can be used (with them) only if they fail as-is.
Hi. I've decided to give a try [1]. As expected it's reasonably simple but I haven't tested it extensively. Actually I'm more interested by a second form that allows to implicitly convert a parameter to a custom type (called opImplicitConvL). [1] : https://github.com/Basile-z/dmd/pull/2 Now as said on IRC, the harder is to write a solid proposal.
Jul 11 2019
prev sibling parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 17.06.19 15:48, Mike Franklin wrote:
 void main()
 {
      S s;
      s = 1;
      int i = s;  // No way to make this work in the library.  We need 
 `opAssignRight`.
 }
 ```
 ...
This is not an assignment. It is an initialization. opAssignRight would do nothing for this case.
 I think if we had an `opAssignRight` feature (with friends) we could 
 move the entire implementation of `alias this` to the library.
I don't think that works. (And I don't necessarily agree that it is desirable. See Ethan's excellent post noting issues with compile times.) This is another case you can't do in the library right now: struct S{ int x; alias x this; } int foo(int x){ return x; } void main(){ import std.stdio; writeln(foo(S(3))); }
Jun 17 2019
next sibling parent reply 12345swordy <alexanderheistermann gmail.com> writes:
On Monday, 17 June 2019 at 18:31:18 UTC, Timon Gehr wrote:
 On 17.06.19 15:48, Mike Franklin wrote:
 void main()
 {
      S s;
      s = 1;
      int i = s;  // No way to make this work in the library.  
 We need `opAssignRight`.
 }
 ```
 ...
This is not an assignment. It is an initialization. opAssignRight would do nothing for this case.
 I think if we had an `opAssignRight` feature (with friends) we 
 could move the entire implementation of `alias this` to the 
 library.
I don't think that works. (And I don't necessarily agree that it is desirable. See Ethan's excellent post noting issues with compile times.) This is another case you can't do in the library right now: struct S{ int x; alias x this; } int foo(int x){ return x; } void main(){ import std.stdio; writeln(foo(S(3))); }
AKA implicit conversion. Which D needs if it were to deprecate alias this.
Jun 17 2019
parent user1234 <user1234 12.de> writes:
On Monday, 17 June 2019 at 18:56:13 UTC, 12345swordy wrote:
 On Monday, 17 June 2019 at 18:31:18 UTC, Timon Gehr wrote:
 On 17.06.19 15:48, Mike Franklin wrote:
 [...]
This is not an assignment. It is an initialization. opAssignRight would do nothing for this case.
 [...]
I don't think that works. (And I don't necessarily agree that it is desirable. See Ethan's excellent post noting issues with compile times.) This is another case you can't do in the library right now: struct S{ int x; alias x this; } int foo(int x){ return x; } void main(){ import std.stdio; writeln(foo(S(3))); }
AKA implicit conversion. Which D needs if it were to deprecate alias this.
Yes, the T opImplicitConv(T)(){} mentioned previously could be used for that too. "writeln(foo(S(3)));" rewritten "writeln(foo(S(3).opImplicitConv!int()));"
Jun 17 2019
prev sibling parent reply Mike Franklin <slavo5150 yahoo.com> writes:
On Monday, 17 June 2019 at 18:31:18 UTC, Timon Gehr wrote:
 On 17.06.19 15:48, Mike Franklin wrote:
 void main()
 {
      S s;
      s = 1;
      int i = s;  // No way to make this work in the library.  
 We need `opAssignRight`.
 }
This is not an assignment. It is an initialization. opAssignRight would do nothing for this case.
I don't disagree, but that's not what `alias this` does. ``` struct S { int i = 42; alias i this; } void main() { S s; int i = s; writeln("Init: ", i.init, " Value: ", i); } ``` https://run.dlang.io/is/ra5may Output: Init: 0 Value: 42
 I think if we had an `opAssignRight` feature (with friends) we 
 could move the entire implementation of `alias this` to the 
 library.
I don't think that works. (And I don't necessarily agree that it is desirable. See Ethan's excellent post noting issues with compile times.)
Sorry, I couldn't find the post. If you explicitly reference it, I'll read it. If you're saying that implementing `alias this` in the library would negatively affect compile times, I think you may be right. But that is a performance bug in the compiler's implementation. newCTFE and other efforts could help alleviate that. In general, I thought it was preferred to delegate features to the library instead of further complicating the compiler. See https://github.com/dlang/dmd/pull/7988
 This is another case you can't do in the library right now:

 struct S{
     int x;
     alias x this;
 }

 int foo(int x){
     return x;
 }

 void main(){
     import std.stdio;
     writeln(foo(S(3)));
 }
The idea would be for the compiler to lower to something like: ``` int tmp; s.opAssignRight(tmp); // passed as `ref` foo(tmp); ``` That's probably still not right, but I think there is a lowering that would work. multiple alias this (i.e. DIP66) was approved almost 5 years ago and despite mutliple attempts at the implementation, it still has not materialized. The primary blocker is the complexity it introduced in the compiler (https://github.com/dlang/dmd/pull/8378#issuecomment-403261763). Multiple alias this is not going to happen unless it's delegated to the library. It seems to me that the best way forward is whatever language feature is missing (`opAssignRight`, `opImplicitCast`, `opWhatever`) so it can be implemented in the library, and potentially enable additional idioms in D at the same time. Mike
Jun 17 2019
parent Timon Gehr <timon.gehr gmx.ch> writes:
On 18.06.19 02:01, Mike Franklin wrote:
 On Monday, 17 June 2019 at 18:31:18 UTC, Timon Gehr wrote:
 On 17.06.19 15:48, Mike Franklin wrote:
 void main()
 {
      S s;
      s = 1;
      int i = s;  // No way to make this work in the library. We need 
 `opAssignRight`.
 }
This is not an assignment. It is an initialization. opAssignRight would do nothing for this case.
I don't disagree, but that's not what `alias this` does. ``` struct S {     int i = 42;     alias i this; } void main() {     S s;     int i = s;     writeln("Init: ", i.init, " Value: ", i); } ``` https://run.dlang.io/is/ra5may Output: Init: 0 Value: 42 ...
I am not sure what your point is. Initializations don't affect the .init value: struct S{ int x=42; pragma(msg,x.init); // 0 } void main(){ int x=42; pragma(msg,x.init); // 0 }
 I think if we had an `opAssignRight` feature (with friends) we could 
 move the entire implementation of `alias this` to the library.
I don't think that works. (And I don't necessarily agree that it is desirable. See Ethan's excellent post noting issues with compile times.)
Sorry, I couldn't find the post.  If you explicitly reference it, I'll read it.
It's easy to find in the threaded view of a news reader. The relevant part is this: On 17.06.19 19:41, Ethan wrote:
 Without multiple alias this, you have to do exactly what I do with
 Binderoo C++ binding and parse each relevant object to generate wrapper
 functions for it. Up goes the compile time. 
 If you're saying that implementing `alias this` in the library 
 would negatively affect compile times, I think you may be right.  But 
 that is a performance bug in the compiler's implementation.  newCTFE and 
 other efforts could help alleviate that.
Maybe, but I doubt that iterating over all members of a structure and generating code for each of them will ever be very fast.
 ...
 
 multiple alias this (i.e. DIP66) was approved almost 5 years ago and 
 despite mutliple attempts at the implementation, it still has not 
 materialized.  The primary blocker is the complexity it introduced in 
 the compiler 
 (https://github.com/dlang/dmd/pull/8378#issuecomment-403261763). 
 Multiple alias this is not going to happen unless it's delegated to the 
 library.  It seems to me that the best way forward is whatever language 
 feature is missing (`opAssignRight`, `opImplicitCast`, `opWhatever`) so 
 it can be implemented in the library, and potentially enable additional 
 idioms in D at the same time.
 
 Mike
There should be opImplicitCast for conversions, but I don't know how you would import scopes correctly (with multiple overload sets that have the same name, etc) without compiler support. For a significant subset of use cases, it would suffice if in addition to opImplicitCast, this just worked: struct T{ int x; } struct S{ T t; alias x=t.x; } void main(){ S s; import std.stdio; writeln(s.x); // Error: need `this` for `x` of type `int` } If this was made to work, probably multiple `alias this` could be implemented semi-correctly by generating some mixin templates that mix in such alias declarations.
Jun 17 2019