digitalmars.D - Multiple alias this, what's the hold up?
- Amex (69/69) Jun 15 2019 How many years has it been in limbo? 1? 2? 3? 5? 10?
- 12345swordy (5/7) Jun 15 2019 What the hold up is that walter thinks it is a bad idea to
- Jonathan Marler (8/16) Jun 15 2019 Maybe we could add it as an optional feature enabled with a
- Timon Gehr (7/27) Jun 15 2019 In terms of lookup, the issues with multiple alias this are the same as
- Walter Bright (3/7) Jun 15 2019 Multiple alias this is multiple inheritance. Generally, if you find your...
- Jonathan Marler (49/59) Jun 15 2019 There's not many cases where I've really needed/wanted multiple
- Mike Franklin (7/13) Jun 16 2019 If one should prefer composition to inheritance the language must
- Walter Bright (5/13) Jun 16 2019 Be careful about dismissing what experts say. Sometimes it takes many ye...
- Mike Franklin (12/24) Jun 16 2019 I think you may have misunderstood what that user and I are
- Timon Gehr (8/19) Jun 16 2019 No. It's multiple imports. You have no vtable to populate, so you can
- Walter Bright (7/18) Jun 16 2019 D already has multiple imports with template mixins. If multiple imports...
- Adam D. Ruppe (7/11) Jun 16 2019 Actually, I'll disagree with both of you. I think alias this is
- Timon Gehr (10/21) Jun 16 2019 Sure, it does that too, but this doesn't really inform the design.
- Timon Gehr (13/22) Jun 16 2019 No. Mixins and imports are not the same thing. E.g., this code is fine:
- Walter Bright (3/4) Jun 17 2019 Template mixins are something else:
- Timon Gehr (23/29) Jun 17 2019 In my answer I explicitly stated that for the purpose of my argument,
- Exil (16/36) Jun 17 2019 Isn't there an entire thread arguing for the inclusion of
- Amex (27/37) Jun 16 2019 This is not true! Alias this is does not use inheritance at all.
- Guillaume Piolat (4/14) Jun 16 2019 +1
- Ethan (79/82) Jun 17 2019 I'm going to voice up for the "not generally" case.
- Olivier FAURE (19/23) Jun 18 2019 I agree with you that D has great potential as tool to write an
- =?UTF-8?Q?Ali_=c3=87ehreli?= (7/17) Jun 18 2019 Does this mean multiple alias this will never happen?
- Jonathan M Davis (20/36) Jun 18 2019 It definitely looks like a DIP would be required for multiple alias this...
- Mike Franklin (4/8) Jun 18 2019 DIP66 (https://wiki.dlang.org/DIP66) was already created and
- Jonathan M Davis (6/13) Jun 18 2019 Given Walter's more recent statements on the matter, it doesn't sound li...
- Jonathan Marler (8/24) Jun 18 2019 It's fair to say that multiple alias this and multiple
- aliak (28/54) Jun 19 2019 That's not to say that alias this itself doesn't have its design
- Les De Ridder (4/16) Jun 19 2019 If that's indeed the case it should probably be removed from the
- Jonathan M Davis (7/25) Jun 19 2019 IMHO, regardless of whether we intend to add the ability to have multipl...
- Jonathan Marler (17/45) Jun 15 2019 Having a hard time trying to figure out what you mean here. I'm
- Timon Gehr (27/78) Jun 16 2019 Probably. What I mean is multiple imports of different modules:
- Jonathan Marler (19/91) Jun 16 2019 Now I gotcha.
- aliak (10/16) Jun 16 2019 That reminded me of private symbols that are publicly aliased.
- Mike Franklin (61/63) Jun 16 2019 DIP66 is in need of champion. Do you wish to adopt
- Adam D. Ruppe (43/53) Jun 17 2019 It has kinda become my thing to comment on this whenever I can,
- Mike Franklin (40/54) Jun 17 2019 I know and thank you for posting improvements, but it was just an
- Jonathan Marler (3/9) Jun 17 2019 +1 to discuss opAssignRight
- user1234 (9/13) Jun 17 2019 At first glance opAssignRight is a really **brilliant** idea 👍.
- rikki cattermole (4/17) Jun 17 2019 Oh I like this.
- user1234 (5/25) Jun 17 2019 It looks very much like "opCast" actually and a better named is
- rikki cattermole (7/11) Jun 17 2019 I thought about opCast as well, and it does look like it. But its not
- user1234 (3/14) Jun 17 2019 Semantics to call this possibly new operator must be well defined
- Mike Franklin (2/4) Jun 17 2019 Indeed.
- user1234 (22/49) Sep 06 I've implemented that yesteday and the first problem I
- Basile B. (8/28) Jul 11 2019 Hi. I've decided to give a try [1]. As expected it's reasonably
- Timon Gehr (17/28) Jun 17 2019 This is not an assignment. It is an initialization. opAssignRight would
- 12345swordy (3/33) Jun 17 2019 AKA implicit conversion. Which D needs if it were to deprecate
- user1234 (5/35) Jun 17 2019 Yes, the T opImplicitConv(T)(){} mentioned previously could be
- Mike Franklin (46/74) Jun 17 2019 I don't disagree, but that's not what `alias this` does.
- Timon Gehr (36/100) Jun 17 2019 I am not sure what your point is. Initializations don't affect the .init...
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
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
On Saturday, 15 June 2019 at 23:30:09 UTC, 12345swordy wrote:On Saturday, 15 June 2019 at 10:12:46 UTC, Amex 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 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.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
On 16.06.19 03:04, Jonathan Marler wrote:On Saturday, 15 June 2019 at 23:30:09 UTC, 12345swordy wrote:That probably won't fly.On Saturday, 15 June 2019 at 10:12:46 UTC, Amex 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. ...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.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
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
On Sunday, 16 June 2019 at 06:08:54 UTC, Walter Bright wrote:On 6/15/2019 6:21 PM, Timon Gehr wrote: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 :)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
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++ orMike
Jun 16 2019
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: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 find it annoying that C++ experts make statements like "Prefer composition the "right thing".
Jun 16 2019
On Sunday, 16 June 2019 at 22:28:56 UTC, Walter Bright wrote: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!"? MikeI 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: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 find it annoying that C++ experts make statements like "Prefer composition to inheritance" yet the language (C++ or
Jun 16 2019
On 16.06.19 08:08, Walter Bright wrote:On 6/15/2019 6:21 PM, Timon Gehr wrote: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.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.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
On 6/16/2019 7:39 AM, Timon Gehr wrote:On 16.06.19 08:08, Walter Bright wrote:D already has multiple imports with template mixins. If multiple imports is what people want, it's already there.Multiple alias this is multiple inheritance.No. It's multiple imports.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.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
On Sunday, 16 June 2019 at 22:14:19 UTC, Walter Bright wrote:On 6/16/2019 7:39 AM, Timon Gehr wrote: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.No. It's multiple imports.D already has multiple imports with template mixins. If multiple imports is what people want, it's already there.
Jun 16 2019
On 17.06.19 00:28, Adam D. Ruppe wrote:On Sunday, 16 June 2019 at 22:14:19 UTC, Walter Bright wrote: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.On 6/16/2019 7:39 AM, Timon Gehr wrote: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. ...No. It's multiple imports.D already has multiple imports with template mixins. If multiple imports is what people want, it's already there.
Jun 16 2019
On 17.06.19 00:14, Walter Bright wrote:On 6/16/2019 7:39 AM, Timon Gehr wrote: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.)On 16.06.19 08:08, Walter Bright wrote:D already has multiple imports with template mixins. If multiple imports is what people want, it's already there. ...Multiple alias this is multiple inheritance.No. It's multiple imports.
Jun 16 2019
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
On 17.06.19 09:29, Walter Bright wrote:On 6/16/2019 4:46 PM, Timon Gehr wrote: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#L3348mixin(import("std/stdio.d"));Template mixins are something else: https://dlang.org/spec/template-mixin.html
Jun 17 2019
On Sunday, 16 June 2019 at 22:14:19 UTC, Walter Bright wrote:On 6/16/2019 7:39 AM, Timon Gehr wrote: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).On 16.06.19 08:08, Walter Bright wrote:D already has multiple imports with template mixins. If multiple imports is what people want, it's already there.Multiple alias this is multiple inheritance.No. It's multiple imports.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.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.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 17 2019
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:The diamond problem in theory is possible but the compiler implementation would error with recursion when making type semantic.On 6/16/2019 7:39 AM, Timon Gehr wrote: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).On 16.06.19 08:08, Walter Bright wrote:D already has multiple imports with template mixins. If multiple imports is what people want, it's already there.Multiple alias this is multiple inheritance.No. It's multiple imports.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.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.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 18 2019
On Tuesday, 18 June 2019 at 23:33:12 UTC, user1234 wrote:On Tuesday, 18 June 2019 at 00:58:58 UTC, Exil wrote: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/EqliF5On Sunday, 16 June 2019 at 22:14:19 UTC, Walter Bright wrote:The diamond problem in theory is possible but the compiler implementation would error with recursion when making type semantic.On 6/16/2019 7:39 AM, Timon Gehr wrote: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).On 16.06.19 08:08, Walter Bright wrote:D already has multiple imports with template mixins. If multiple imports is what people want, it's already there.Multiple alias this is multiple inheritance.No. It's multiple imports.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.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.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 18 2019
On Sunday, 16 June 2019 at 06:08:54 UTC, Walter Bright wrote:On 6/15/2019 6:21 PM, Timon Gehr wrote: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?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 16 2019
On Sunday, 16 June 2019 at 06:08:54 UTC, Walter Bright wrote:On 6/15/2019 6:21 PM, Timon Gehr wrote:+1 And in D I've "needed" multiple inheritance exactly once, so I wonder what is the use case for multiple alias this...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 16 2019
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
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
On 06/15/2019 11:08 PM, Walter Bright wrote:On 6/15/2019 6:21 PM, Timon Gehr wrote: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. AliIn 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 18 2019
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: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 DavisOn 6/15/2019 6:21 PM, Timon Gehr wrote: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.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 18 2019
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
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: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 DavisIt 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?
Jun 18 2019
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: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.On Tuesday, 18 June 2019 at 22:51:51 UTC, Jonathan M Davis wrote: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 DavisIt 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?
Jun 18 2019
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: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.On Tuesday, June 18, 2019 10:09:24 PM MDT Mike Franklin via Digitalmars-d wrote: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.On Tuesday, 18 June 2019 at 22:51:51 UTC, Jonathan M Davis wrote: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 DavisIt 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?
Jun 19 2019
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
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: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[...] 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
On Sunday, 16 June 2019 at 01:21:16 UTC, Timon Gehr wrote:On 16.06.19 03:04, Jonathan Marler wrote: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.On Saturday, 15 June 2019 at 23:30:09 UTC, 12345swordy wrote:That probably won't fly.On Saturday, 15 June 2019 at 10:12:46 UTC, Amex 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. ...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.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
On 16.06.19 08:19, Jonathan Marler wrote:On Sunday, 16 June 2019 at 01:21:16 UTC, Timon Gehr wrote: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.On 16.06.19 03:04, Jonathan Marler wrote: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? ...On Saturday, 15 June 2019 at 23:30:09 UTC, 12345swordy wrote:That probably won't fly.On Saturday, 15 June 2019 at 10:12:46 UTC, Amex 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. ...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.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 16 2019
On Sunday, 16 June 2019 at 14:23:37 UTC, Timon Gehr wrote:On 16.06.19 08:19, Jonathan Marler wrote: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()).On Sunday, 16 June 2019 at 01:21:16 UTC, Timon Gehr wrote: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.On 16.06.19 03:04, Jonathan Marler wrote: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? ...On Saturday, 15 June 2019 at 23:30:09 UTC, 12345swordy wrote:That probably won't fly.[...]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.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 16 2019
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
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
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
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: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. MikeContrived, 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.
Jun 17 2019
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:+1 to discuss opAssignRight That would solve my sentinel module problem.[...]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. [...]
Jun 17 2019
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. [...] MikeAt 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
On 18/06/2019 3:58 AM, user1234 wrote:On Monday, 17 June 2019 at 13:48:45 UTC, Mike Franklin wrote: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.I think if we had an `opAssignRight` feature (with friends) we could move the entire implementation of `alias this` to the library. [...] MikeAt 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
On Monday, 17 June 2019 at 16:13:07 UTC, rikki cattermole wrote:On 18/06/2019 3:58 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...".On Monday, 17 June 2019 at 13:48:45 UTC, Mike Franklin wrote: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.I think if we had an `opAssignRight` feature (with friends) we could move the entire implementation of `alias this` to the library. [...] MikeAt 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
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
On Monday, 17 June 2019 at 16:27:59 UTC, rikki cattermole wrote:On 18/06/2019 4:18 AM, user1234 wrote:Semantics to call this possibly new operator must be well defined -> DIPIt 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
On Monday, 17 June 2019 at 17:39:54 UTC, user1234 wrote:Semantics to call this possibly new operator must be well defined -> DIPIndeed.
Jun 17 2019
On Monday, 17 June 2019 at 16:18:55 UTC, user1234 wrote:On Monday, 17 June 2019 at 16:13:07 UTC, rikki cattermole wrote:I've implemented that yesteday and the first problem I encountered was "wait that should work directly". So the problem you have with that solution is that the operator overload that gives the data that is controlled is rarely needed. Most of the time you have to overload each every fucking operators. So in the end you end up with the exact same thing as `alias this`. Simple exmple ```d a = b; ``` Here in this case a compiler does not try to find the mutual common type of `a` and `b`. Instead it just tries to see if `b` type can convert to the `a` one. With `alias this`, eventually the compiler has to try if `a` can yield a lvalue of `b` type. In the end that's the exact same problem. That adds complexity for a special case. For every each case where implicit conv is not tried, you also have to try `alias this` or the alternative `opImplicitConvRight`. It's the same thing.On 18/06/2019 3:58 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...".On Monday, 17 June 2019 at 13:48:45 UTC, Mike Franklin wrote: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.I think if we had an `opAssignRight` feature (with friends) we could move the entire implementation of `alias this` to the library. [...] MikeAt 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();
Sep 06
On Monday, 17 June 2019 at 16:13:07 UTC, rikki cattermole wrote:On 18/06/2019 3:58 AM, user1234 wrote: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.On Monday, 17 June 2019 at 13:48:45 UTC, Mike Franklin wrote: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.I think if we had an `opAssignRight` feature (with friends) we could move the entire implementation of `alias this` to the library. [...] MikeAt 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();
Jul 11 2019
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
On Monday, 17 June 2019 at 18:31:18 UTC, Timon Gehr wrote:On 17.06.19 15:48, Mike Franklin wrote:AKA implicit conversion. Which D needs if it were to deprecate alias this.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
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:Yes, the T opImplicitConv(T)(){} mentioned previously could be used for that too. "writeln(foo(S(3)));" rewritten "writeln(foo(S(3).opImplicitConv!int()));"On 17.06.19 15:48, Mike Franklin wrote:AKA implicit conversion. Which D needs if it were to deprecate alias this.[...]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))); }
Jun 17 2019
On Monday, 17 June 2019 at 18:31:18 UTC, Timon Gehr wrote:On 17.06.19 15:48, Mike Franklin wrote: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: 42void 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.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/7988I 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))); }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
On 18.06.19 02:01, Mike Franklin wrote:On Monday, 17 June 2019 at 18:31:18 UTC, Timon Gehr wrote: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 }On 17.06.19 15:48, Mike Franklin wrote: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 ...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.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:Sorry, I couldn't find the post. If you explicitly reference it, I'll read it.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.)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. MikeThere 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