digitalmars.D - DIP66 - Multiple alias this
- IgorStepanov (4/4) Oct 10 2014 I've created DIP for my pull request.
- Steven Schveighoffer (5/9) Oct 10 2014 Hm... not sure you need a DIP.
- IgorStepanov (6/16) Oct 10 2014 TDPL tells that multiple alias this should be allowed, but tell
- Brad Anderson (5/15) Oct 10 2014 Igor was asked to write a DIP for it by Walter and Andrei. Here's
- Andrei Alexandrescu (2/11) Oct 10 2014 TDPL is not reference. The DIP should cover various corner cases. -- And...
- Steven Schveighoffer (4/16) Oct 10 2014 OK, thanks everyone. I thought DIPs were specifically for proposals that...
- Andrei Alexandrescu (2/6) Oct 10 2014 Thanks, will do. Everybody interested please chime in! -- Andrei
- Brian Schott (4/8) Oct 10 2014 There is an error in the wiki formatting in the second code
- IgorStepanov (2/11) Oct 10 2014 Fixed. This is starnge implicit copy-paste of my text editor =/
- "Marc =?UTF-8?B?U2Now7x0eiI=?= <schuetzm gmx.net> (9/13) Oct 10 2014 I understand that as a first step it was suggested to implement
- IgorStepanov (6/20) Oct 10 2014 There isn't hard to change resolving strategy. This will need to
- Steven Schveighoffer (17/21) Oct 10 2014 This part:
- IgorStepanov (54/78) Oct 10 2014 I thought exactly about this using case.
- Steven Schveighoffer (36/114) Oct 10 2014 Why? It's just as confused as before, no?
- IgorStepanov (4/134) Oct 10 2014 You can write foo(c.shadow); This isn't hard.
- Steven Schveighoffer (9/48) Oct 12 2014 Right, you can get around it.
- IgorStepanov (7/61) Oct 12 2014 Hmm. I've written case (my previous post), when returning false
- Steven Schveighoffer (22/39) Oct 12 2014 OK, I didn't understand your case before, but I just got it.
- IgorStepanov (7/55) Oct 13 2014 This is fundamentally different situation: interfaces haven't a
- IgorStepanov (5/5) Oct 12 2014 Advantage of ky way is a more strictness then your way: if
- IgorStepanov (3/6) Oct 10 2014 In this case, you will see the real error and will able to fix
- Walter Bright (2/6) Oct 10 2014 Thanks, Igor!
- Walter Bright (19/21) Oct 10 2014 Comment should say that C is implicitly convertible to int
- Timon Gehr (3/6) Oct 10 2014 Agreed. Do you suggest to overload alias this against imports and mixin
- Walter Bright (4/10) Oct 10 2014 I hadn't thought of that (thanks for bringing it up). My first thought i...
- Timon Gehr (21/33) Oct 10 2014 This allows for symbol hijacking (this is also the current behaviour):
- Walter Bright (2/36) Oct 10 2014 Hmm. Good point. The alias this should be done before imports.
- IgorStepanov (3/55) Oct 10 2014 Symmetrically. You may use symbol from import, uncomment it in
- IgorStepanov (4/4) Oct 10 2014 BTW.
- IgorStepanov (37/62) Oct 10 2014 Not really.
- Timon Gehr (14/42) Oct 10 2014 The pseudo-code doesn't actually specify that the arguments the
- IgorStepanov (7/55) Oct 10 2014 C.foo("test"); //Ok, C.b.foo(string);
- Timon Gehr (51/55) Oct 10 2014 - "C c;
- IgorStepanov (28/85) Oct 10 2014 C++ allowed subtypes, which can not be casted to the base type
- Walter Bright (8/31) Oct 10 2014 The rule would be if:
- IgorStepanov (2/41) Oct 10 2014 So it is.
- Walter Bright (3/7) Oct 10 2014 Good!
- IgorStepanov (28/37) Oct 11 2014 I've implemented overloading:
- Walter Bright (7/44) Oct 11 2014 At the very least, it should say it resolves ambiguities the same way th...
- "Marc =?UTF-8?B?U2Now7x0eiI=?= <schuetzm gmx.net> (4/36) Oct 12 2014 It's the same type, but different symbols; actual accesses would
- IgorStepanov (84/121) Oct 12 2014 I found an example of a situation that is bothering me.
- Daniel N (6/26) Oct 13 2014 My preferred solution would be to reject the 2nd alias
- IgorStepanov (13/39) Oct 14 2014 This code tell that C is subtype of A and C is subtype of B.
- Dicebot (4/16) Oct 14 2014 I agree. It will also make possible to break already working
- Daniel N (22/39) Oct 14 2014 I guess the best part of D is, you have the means to fix anything
- IgorStepanov (8/49) Oct 15 2014 In first edition I've implemented rule, when if type defines
- IgorStepanov (1/1) Oct 19 2014 Bump.
- Dicebot (3/4) Oct 21 2014 For me current description and PR look solid and safe enough to
- IgorStepanov (3/7) Oct 21 2014 We are waiting for an Andrey's Word. Walter, as I understand
- Andrei Alexandrescu (2/9) Oct 27 2014 There are issues with the proposal. I must get to them today. -- Andrei
- Andrei Alexandrescu (4/5) Oct 23 2014 I've made a few grammar and fluency edits to the DIP, and collected a
- IgorStepanov (11/16) Oct 24 2014 I've seen it. Thanks!
- Meta (6/23) Oct 24 2014 The convention is to write "etc.", with the period indicating
- John Colvin (4/29) Oct 24 2014 A full stop (a.k.a. period in some countries) for abbreviation
- IgorStepanov (2/27) Oct 24 2014 Thanks for the explanation:)
- Andrei Alexandrescu (6/21) Oct 27 2014 Interesting. I think it should work like overloading of calls in base
- IgorStepanov (96/123) Oct 28 2014 Not really. Rules which define overloading class methods doesn't
- Daniel N (4/11) Oct 19 2014 I see, in order to prevent any accidental shadowing, maybe one
- IgorStepanov (6/19) Oct 19 2014 Make sense. I think we should postpone but not forgotten this
- Joseph Rushton Wakeling via Digitalmars-d (8/12) Oct 10 2014 This may be beyond the scope of the DIP, but is there any intention (or ...
- Walter Bright (4/17) Oct 10 2014 I like the C++ rule that says that access control is not considered for ...
- Jacob Carlborg (7/10) Oct 11 2014 I'm not so sure about that. Perhaps it makes it more understandable for
- Walter Bright (3/11) Oct 11 2014 The theory is that simpler rules are better than complex rules, even if ...
- Timon Gehr (4/19) Oct 12 2014 Public symbols conflicting with private symbols are not just not ideal,
- Joseph Rushton Wakeling via Digitalmars-d (4/7) Oct 12 2014 That's fine. I just wanted to be sure that there wasn't a risk of multi...
- Andrei Alexandrescu (46/50) Oct 28 2014 Here's my destruction:
- IgorStepanov (24/81) Oct 28 2014 Thanks for answer, I hope, I'll able to to carefully consider
- Meta (28/31) Oct 28 2014 Something else related to the discussion about `is` from this
- Meta (2/4) Oct 28 2014 My mistake, I mean isNaN and similar functions, such as isNumeric.
- IgorStepanov (8/39) Oct 28 2014 You may see isFloatingPoint declaration in traits.d:
- Meta (7/14) Oct 28 2014 Although alias this is supposed to denote subtyping, here is a
- IgorStepanov (15/30) Oct 29 2014 Your issue is not relevant with alias this implementation.
- "Ola Fosheim =?UTF-8?B?R3LDuHN0YWQi?= (7/7) Oct 28 2014 You should rethink implementing multiple alias this. D is
- Dicebot (6/13) Oct 31 2014 No.
- Mike B Johnson (2/6) Jun 04 2017 Well, nearly 3 years later and nothing!
- sighoya (2/6) Mar 20 2019 What's the state?
- Mike Franklin (6/13) Mar 20 2019 https://github.com/dlang/dmd/pull/8378
- sighoya (2/16) Mar 20 2019 How can I help if I'm not the one creating the PR?
- Mike Franklin (7/8) Mar 20 2019 It needs someone willing to adopt the PR and work with reviewers
- sighoya (4/12) Mar 21 2019 So I can become a reviewer only, but how can I propose changes to
- Mike Franklin (5/9) Mar 21 2019 Create a new branch, merge the original author's work into your
- sighoya (4/8) Mar 21 2019 Glad to hear.
- Mike Franklin (3/12) Mar 21 2019 IMO, yes.
- sighoya (4/12) Mar 21 2019 So I can become a reviewer only, but how can I merge additions
- IGotD- (6/10) Sep 27 2020 What happened to this dip? Do we have an implementation or not
- 12345swordy (5/16) Sep 27 2020 It been deprecated as Walter discovered that the current alias
- IGotD- (7/11) Sep 27 2020 It doesn't because it isn't inheritance. What you can end up with
- 12345swordy (7/15) Sep 27 2020 Walter has comment on this on reddit already. It is not
- IGotD- (9/13) Sep 27 2020 Yes, exactly that, creating multiple composites. I know that you
- 12345swordy (4/20) Sep 27 2020 That is the solution that Walter has suggest to us. What issue
- Ruby The Roobster (2/6) Sep 27 2020 Couldn't this be fixed by not having inheritance of alias this?
- IGotD- (15/19) Sep 28 2020 I must criticize the cop out that many language designers claim
- 12345swordy (5/21) Sep 28 2020 Then by all means created a new thread on this and argue your
- IGotD- (9/13) Sep 28 2020 First limit multiple alias this to only be valid for basic types
- mw (7/22) Sep 28 2020 I think this deserved to be better known:
- H. S. Teoh (8/17) Sep 28 2020 That award has nothing to do with the diamond problem. There is nothing
- mw (15/19) Sep 28 2020 D has `alias` already, which can be used as Eiffel's `rename`,
- H. S. Teoh (8/15) Sep 28 2020 [...]
- mw (12/27) Sep 28 2020 On a second thought, I agree we'd better not to extend `alias`.
- H. S. Teoh (45/56) Sep 28 2020 I don't know Eiffel; could you enlighten me as to how it solves the
- mw (60/100) Sep 28 2020 The Resource A.x in your example is what I have shown in my
- mw (11/17) Sep 28 2020 I didn't handle just 2 cases, but all kinds of cases, whether in
- H. S. Teoh (9/29) Sep 28 2020 Good. Now make it work for D. :-P
- mw (16/21) Sep 28 2020 Not sure what you mean by dynamic memory layout.
- IGotD- (14/20) Sep 28 2020 So what is the alternative? I'm not that enthusiastic of mixin
- Andrei Alexandrescu (5/18) Sep 28 2020 I'd love to get a better idea about this, e.g. a few clear examples of
- Andrei Alexandrescu (2/22) Sep 28 2020 s/year/yearn/
- 12345swordy (9/33) Sep 28 2020 An example of bad use is when you "alias this" a class inside a
- Walter Bright (11/14) Sep 28 2020 There are several bugzilla issues on alias this that aren't fixed becaus...
- 12345swordy (7/21) Sep 29 2020 You could take Manu Evans advice and allow structs to inherent
- Paul Backus (5/10) Sep 29 2020 I did a grep for `alias this` in Phobos last time this topic came
- Andrei Alexandrescu (2/14) Sep 29 2020 How frequently did the method return ref vs rvalue?
- Mike (127/140) Sep 29 2020 What's good about `alias this`
- Mike (2/14) Sep 29 2020 4. Somehow allow structs to implement interfaces.
- Andrei Alexandrescu (3/22) Sep 29 2020 I'd love it if interfaces could implement methods. (All MI related
- Andrei Alexandrescu (2/25) Sep 29 2020 BTW forgot to mention - this is from the category of removing limitation...
- Mike (9/33) Sep 29 2020 FWIW, C# 8 recently added such a feature. They call it "Default
- H. S. Teoh (15/26) Sep 29 2020 Don't we already have this in D?
- Steven Schveighoffer (5/31) Sep 29 2020 It looks like default method bodies are virtual and can be overridden.
- H. S. Teoh (9/32) Sep 29 2020 [...]
- rikki cattermole (5/6) Sep 29 2020 Alternatively signatures.
- IGotD- (2/3) Sep 30 2020 Wouldn't that mean a vtable and therefore a POD violation?
- Paolo Invernizzi (4/10) Sep 30 2020 This!
- Simen =?UTF-8?B?S2rDpnLDpXM=?= (7/19) Sep 30 2020 There's quite a few tests in Phobos for alias this on classes,
- H. S. Teoh (10/22) Sep 30 2020 [...]
- Paolo Invernizzi (6/30) Sep 30 2020 Indeed, I imagine that's a much simpler case to handle in the
- Mike (7/16) Sep 30 2020 To be more precise, you don't actually have to deprecated alias
- Carl Sturtivant (5/10) Aug 05 2021 Yes, an extension for structs only seems like a good way to avoid
- IGotD- (7/17) Sep 30 2020 4. Remove "alias this" completely, use mixin templates instead. I
- IGotD- (6/11) Sep 29 2020 As it seems, the language maintainers want to remove alias this
- IGotD- (11/25) Sep 29 2020 Further more, this in the "alias this" documentation.
- Andrei Alexandrescu (2/25) Sep 29 2020 Ouch. A PR to change that would be in order regardless of future actions...
- Andrei Alexandrescu (3/29) Sep 29 2020 Time waits for no one.
- mw (15/25) Sep 28 2020 The two hallmarks of Eiffel, is design-by-contract and multiple
I've created DIP for my pull request. DIP: http://wiki.dlang.org/DIP66 PR: https://github.com/D-Programming-Language/dmd/pull/3998 Please, comment it.
Oct 10 2014
On 10/10/14 1:09 PM, IgorStepanov wrote:I've created DIP for my pull request. DIP: http://wiki.dlang.org/DIP66 PR: https://github.com/D-Programming-Language/dmd/pull/3998 Please, comment it.Hm... not sure you need a DIP. From page 231 of TDPL: "A class could introduce any number of alias this declarations, thus subtyping any number of types." -Steve
Oct 10 2014
On Friday, 10 October 2014 at 17:31:23 UTC, Steven Schveighoffer wrote:On 10/10/14 1:09 PM, IgorStepanov wrote:TDPL tells that multiple alias this should be allowed, but tell nothing about conflict resolving. General idea of this DIP is sistematize rules for alias this. Please comment this part. Maybe I've forgot some cases, maybe introduce dangerous semantic rule.I've created DIP for my pull request. DIP: http://wiki.dlang.org/DIP66 PR: https://github.com/D-Programming-Language/dmd/pull/3998 Please, comment it.Hm... not sure you need a DIP. From page 231 of TDPL: "A class could introduce any number of alias this declarations, thus subtyping any number of types." -Steve
Oct 10 2014
On Friday, 10 October 2014 at 17:31:23 UTC, Steven Schveighoffer wrote:On 10/10/14 1:09 PM, IgorStepanov wrote:Igor was asked to write a DIP for it by Walter and Andrei. Here's the context: https://github.com/D-Programming-Language/dmd/pull/3998#issuecomment-58286631I've created DIP for my pull request. DIP: http://wiki.dlang.org/DIP66 PR: https://github.com/D-Programming-Language/dmd/pull/3998 Please, comment it.Hm... not sure you need a DIP. From page 231 of TDPL: "A class could introduce any number of alias this declarations, thus subtyping any number of types." -Steve
Oct 10 2014
On 10/10/14, 10:31 AM, Steven Schveighoffer wrote:On 10/10/14 1:09 PM, IgorStepanov wrote:TDPL is not reference. The DIP should cover various corner cases. -- AndreiI've created DIP for my pull request. DIP: http://wiki.dlang.org/DIP66 PR: https://github.com/D-Programming-Language/dmd/pull/3998 Please, comment it.Hm... not sure you need a DIP. From page 231 of TDPL: "A class could introduce any number of alias this declarations, thus subtyping any number of types."
Oct 10 2014
On 10/10/14 2:17 PM, Andrei Alexandrescu wrote:On 10/10/14, 10:31 AM, Steven Schveighoffer wrote:OK, thanks everyone. I thought DIPs were specifically for proposals that had not been already approved. -SteveOn 10/10/14 1:09 PM, IgorStepanov wrote:TDPL is not reference. The DIP should cover various corner cases. -- AndreiI've created DIP for my pull request. DIP: http://wiki.dlang.org/DIP66 PR: https://github.com/D-Programming-Language/dmd/pull/3998 Please, comment it.Hm... not sure you need a DIP. From page 231 of TDPL: "A class could introduce any number of alias this declarations, thus subtyping any number of types."
Oct 10 2014
On 10/10/14, 10:09 AM, IgorStepanov wrote:I've created DIP for my pull request. DIP: http://wiki.dlang.org/DIP66 PR: https://github.com/D-Programming-Language/dmd/pull/3998 Please, comment it.Thanks, will do. Everybody interested please chime in! -- Andrei
Oct 10 2014
On Friday, 10 October 2014 at 17:09:08 UTC, IgorStepanov wrote:I've created DIP for my pull request. DIP: http://wiki.dlang.org/DIP66 PR: https://github.com/D-Programming-Language/dmd/pull/3998 Please, comment it.There is an error in the wiki formatting in the second code block. (`{| class="wikitable"` should not be there) I don't see any problems with the actual content of the DIP.
Oct 10 2014
On Friday, 10 October 2014 at 20:29:43 UTC, Brian Schott wrote:On Friday, 10 October 2014 at 17:09:08 UTC, IgorStepanov wrote:Fixed. This is starnge implicit copy-paste of my text editor =/I've created DIP for my pull request. DIP: http://wiki.dlang.org/DIP66 PR: https://github.com/D-Programming-Language/dmd/pull/3998 Please, comment it.There is an error in the wiki formatting in the second code block. (`{| class="wikitable"` should not be there) I don't see any problems with the actual content of the DIP.
Oct 10 2014
On Friday, 10 October 2014 at 17:09:08 UTC, IgorStepanov wrote:I've created DIP for my pull request. DIP: http://wiki.dlang.org/DIP66 PR: https://github.com/D-Programming-Language/dmd/pull/3998 Please, comment it.I understand that as a first step it was suggested to implement the strictest behaviour regarding conflicts, namely to disallow them entirely. However, I think more permissive strategies are useful, like in this example: https://github.com/D-Programming-Language/dmd/pull/3998#issuecomment-58570742 Conflict resolution can work like overload resolution, with different levels of matching and partial ordering.
Oct 10 2014
On Friday, 10 October 2014 at 20:44:11 UTC, Marc Schütz wrote:On Friday, 10 October 2014 at 17:09:08 UTC, IgorStepanov wrote:There isn't hard to change resolving strategy. This will need to change one function definition. Thus we able to implement strictest now and after some time of new feature using, relax the behaviour. This will not require significant efforts.I've created DIP for my pull request. DIP: http://wiki.dlang.org/DIP66 PR: https://github.com/D-Programming-Language/dmd/pull/3998 Please, comment it.I understand that as a first step it was suggested to implement the strictest behaviour regarding conflicts, namely to disallow them entirely. However, I think more permissive strategies are useful, like in this example: https://github.com/D-Programming-Language/dmd/pull/3998#issuecomment-58570742 Conflict resolution can work like overload resolution, with different levels of matching and partial ordering.
Oct 10 2014
On 10/10/14 1:09 PM, IgorStepanov wrote:I've created DIP for my pull request. DIP: http://wiki.dlang.org/DIP66 PR: https://github.com/D-Programming-Language/dmd/pull/3998 Please, comment it.This part: void test() { C c; int i = c; //Error: c.a.i vs c.b.i } static assert(is(C : int)); //Ok, because C is subtype of int anyway. I think might be wrong. There is a lot of code out there that says, e.g.: void foo(T)(T t) if(is(T : U)) { U u = t; ... } Which will now create an error in the wrong place. IMO, the 'is' test should also fail. -Steve
Oct 10 2014
On Friday, 10 October 2014 at 20:47:45 UTC, Steven Schveighoffer wrote:On 10/10/14 1:09 PM, IgorStepanov wrote:I thought exactly about this using case. See: You have a struct like this in first place: struct A { int i; alias i this; } struct C { A a; string s; alias a this; alias s this; } And you have a template function in second place: void foo(T)(T t) if(is(T : int)) { ... } void foo(T)(T t) if(is(T : string)) { ... } And you have the code it third place: C c; foo(c); //Error: what do you mean: foo!(T : string) or foo!(T : int) Now, someone (A developer) changed the A definition: struct A { int i; alias i this; } struct B { int i; alias i this; } struct C { A a; B b; string s; alias a this; alias b this; alias s this; } And now, you code mystically start to works. Attention: Infusing in one place conflict resolves conflict in another place. It is danger, I think.I've created DIP for my pull request. DIP: http://wiki.dlang.org/DIP66 PR: https://github.com/D-Programming-Language/dmd/pull/3998 Please, comment it.This part: void test() { C c; int i = c; //Error: c.a.i vs c.b.i } static assert(is(C : int)); //Ok, because C is subtype of int anyway. I think might be wrong. There is a lot of code out there that says, e.g.: void foo(T)(T t) if(is(T : U)) { U u = t; ... } Which will now create an error in the wrong place. IMO, the 'is' test should also fail. -Steve
Oct 10 2014
On 10/10/14 5:15 PM, IgorStepanov wrote:On Friday, 10 October 2014 at 20:47:45 UTC, Steven Schveighoffer wrote:I agree with all this.On 10/10/14 1:09 PM, IgorStepanov wrote:I thought exactly about this using case. See: You have a struct like this in first place: struct A { int i; alias i this; } struct C { A a; string s; alias a this; alias s this; } And you have a template function in second place: void foo(T)(T t) if(is(T : int)) { ... } void foo(T)(T t) if(is(T : string)) { ... } And you have the code it third place: C c; foo(c); //Error: what do you mean: foo!(T : string) or foo!(T : int)I've created DIP for my pull request. DIP: http://wiki.dlang.org/DIP66 PR: https://github.com/D-Programming-Language/dmd/pull/3998 Please, comment it.This part: void test() { C c; int i = c; //Error: c.a.i vs c.b.i } static assert(is(C : int)); //Ok, because C is subtype of int anyway. I think might be wrong. There is a lot of code out there that says, e.g.: void foo(T)(T t) if(is(T : U)) { U u = t; ... } Which will now create an error in the wrong place. IMO, the 'is' test should also fail. -SteveNow, someone (A developer) changed the A definition: struct A { int i; alias i this; } struct B { int i; alias i this; } struct C { A a; B b; string s; alias a this; alias b this; alias s this; } And now, you code mystically start to works.Why? It's just as confused as before, no? The way the DIP reads, the call to foo(c) compiles, but the instantiation fails. This can cause subtle issues when you want to select an instantiation based on what it casts to. An example: foo(T)(T t) if(is(T : int)) { someFuncThatTakesInt(t); } foo(T)(T t) if(!is(T : int) && is(T.shadow : int)) { someFuncThatTakesInt(t.shadow); } struct A { int i; alias i this; } struct B { int i; alias i this; } struct C { A a; B shadow; alias a this; alias shadow this; } C c; foo(c); // should compile, but I think your DIP makes it fail due to ambiguity -Steve
Oct 10 2014
On Friday, 10 October 2014 at 21:26:49 UTC, Steven Schveighoffer wrote:On 10/10/14 5:15 PM, IgorStepanov wrote:You can write foo(c.shadow); This isn't hard. Ok, I understood you, let's listen to what others sayOn Friday, 10 October 2014 at 20:47:45 UTC, Steven Schveighoffer wrote:I agree with all this.On 10/10/14 1:09 PM, IgorStepanov wrote:I thought exactly about this using case. See: You have a struct like this in first place: struct A { int i; alias i this; } struct C { A a; string s; alias a this; alias s this; } And you have a template function in second place: void foo(T)(T t) if(is(T : int)) { ... } void foo(T)(T t) if(is(T : string)) { ... } And you have the code it third place: C c; foo(c); //Error: what do you mean: foo!(T : string) or foo!(T : int)I've created DIP for my pull request. DIP: http://wiki.dlang.org/DIP66 PR: https://github.com/D-Programming-Language/dmd/pull/3998 Please, comment it.This part: void test() { C c; int i = c; //Error: c.a.i vs c.b.i } static assert(is(C : int)); //Ok, because C is subtype of int anyway. I think might be wrong. There is a lot of code out there that says, e.g.: void foo(T)(T t) if(is(T : U)) { U u = t; ... } Which will now create an error in the wrong place. IMO, the 'is' test should also fail. -SteveNow, someone (A developer) changed the A definition: struct A { int i; alias i this; } struct B { int i; alias i this; } struct C { A a; B b; string s; alias a this; alias b this; alias s this; } And now, you code mystically start to works.Why? It's just as confused as before, no? The way the DIP reads, the call to foo(c) compiles, but the instantiation fails. This can cause subtle issues when you want to select an instantiation based on what it casts to. An example: foo(T)(T t) if(is(T : int)) { someFuncThatTakesInt(t); } foo(T)(T t) if(!is(T : int) && is(T.shadow : int)) { someFuncThatTakesInt(t.shadow); } struct A { int i; alias i this; } struct B { int i; alias i this; } struct C { A a; B shadow; alias a this; alias shadow this; } C c; foo(c); // should compile, but I think your DIP makes it fail due to ambiguity -Steve
Oct 10 2014
On 10/10/14 6:10 PM, IgorStepanov wrote:On Friday, 10 October 2014 at 21:26:49 UTC, Steven Schveighoffer wrote:Right, you can get around it. But the issue here is, that I feel like is(T: U) means (from dlang.org): is ( Type : TypeSpecialization ) The condition is satisfied if Type is semantically correct and it is the same as or can be implicitly converted to TypeSpecialization. This means is(C : int) should indicate that C can implicitly convert to int. But in your DIP, it does not. I think this is incorrect. -SteveAn example: foo(T)(T t) if(is(T : int)) { someFuncThatTakesInt(t); } foo(T)(T t) if(!is(T : int) && is(T.shadow : int)) { someFuncThatTakesInt(t.shadow); } struct A { int i; alias i this; } struct B { int i; alias i this; } struct C { A a; B shadow; alias a this; alias shadow this; } C c; foo(c); // should compile, but I think your DIP makes it fail due to ambiguityYou can write foo(c.shadow); This isn't hard. Ok, I understood you, let's listen to what others say
Oct 12 2014
On Sunday, 12 October 2014 at 23:02:13 UTC, Steven Schveighoffer wrote:On 10/10/14 6:10 PM, IgorStepanov wrote:Hmm. I've written case (my previous post), when returning false from is(T: S), where T has many pathes to S is dangerous. However your words also contain the truth. I don't know what we need to do. Maybe we should raise error during "is" semantic? Please, read my example and say your opinion.On Friday, 10 October 2014 at 21:26:49 UTC, Steven Schveighoffer wrote:Right, you can get around it. But the issue here is, that I feel like is(T: U) means (from dlang.org): is ( Type : TypeSpecialization ) The condition is satisfied if Type is semantically correct and it is the same as or can be implicitly converted to TypeSpecialization. This means is(C : int) should indicate that C can implicitly convert to int. But in your DIP, it does not. I think this is incorrect. -SteveAn example: foo(T)(T t) if(is(T : int)) { someFuncThatTakesInt(t); } foo(T)(T t) if(!is(T : int) && is(T.shadow : int)) { someFuncThatTakesInt(t.shadow); } struct A { int i; alias i this; } struct B { int i; alias i this; } struct C { A a; B shadow; alias a this; alias shadow this; } C c; foo(c); // should compile, but I think your DIP makes it fail due to ambiguityYou can write foo(c.shadow); This isn't hard. Ok, I understood you, let's listen to what others say
Oct 12 2014
On 10/12/14 7:16 PM, IgorStepanov wrote:On Sunday, 12 October 2014 at 23:02:13 UTC, Steven Schveighoffer wrote:On 10/10/14 6:10 PM, IgorStepanov wrote:You can write foo(c.shadow); This isn't hard. Ok, I understood you, let's listen to what others sayRight, you can get around it. But the issue here is, that I feel like is(T: U) means (from dlang.org): is ( Type : TypeSpecialization ) The condition is satisfied if Type is semantically correct and it is the same as or can be implicitly converted to TypeSpecialization. This means is(C : int) should indicate that C can implicitly convert to int. But in your DIP, it does not. I think this is incorrect.Hmm. I've written case (my previous post), when returning false from is(T: S), where T has many pathes to S is dangerous.OK, I didn't understand your case before, but I just got it. I understand what you mean, but this isn't anything new -- one can cause weird problems by creating diamond-pattern interfaces also. I do not actually think it is dangerous, because one would not leave an error call in their code. So for a future change to a library to "mystically" make a function start working is not a danger, because said code wasn't sitting there broken in the first place. I will note, that for diamond problem interfaces, the compiler seems to take a different track than your DIP: interface A {} interface B : A {} interface C : A {} class X : B, C {} static assert(is(X : A)); void main() { A a = new C; // works, not sure if it's B.A or C.A } I know this is a different problem -- we aren't pointing at two different concrete implementations. -Steve
Oct 12 2014
On Monday, 13 October 2014 at 00:54:13 UTC, Steven Schveighoffer wrote:On 10/12/14 7:16 PM, IgorStepanov wrote:This is fundamentally different situation: interfaces haven't a state, thus don't care what interface will be getted: B.C or C.C. Moreover, we can think that we have only one base C (like virtual inherited class in C++). Alias this case requires a completely different approach.On Sunday, 12 October 2014 at 23:02:13 UTC, Steven Schveighoffer wrote:On 10/10/14 6:10 PM, IgorStepanov wrote:You can write foo(c.shadow); This isn't hard. Ok, I understood you, let's listen to what others sayRight, you can get around it. But the issue here is, that I feel like is(T: U) means (from dlang.org): is ( Type : TypeSpecialization ) The condition is satisfied if Type is semantically correct and it is the same as or can be implicitly converted to TypeSpecialization. This means is(C : int) should indicate that C can implicitly convert to int. But in your DIP, it does not. I think this is incorrect.Hmm. I've written case (my previous post), when returning false from is(T: S), where T has many pathes to S is dangerous.OK, I didn't understand your case before, but I just got it. I understand what you mean, but this isn't anything new -- one can cause weird problems by creating diamond-pattern interfaces also. I do not actually think it is dangerous, because one would not leave an error call in their code. So for a future change to a library to "mystically" make a function start working is not a danger, because said code wasn't sitting there broken in the first place. I will note, that for diamond problem interfaces, the compiler seems to take a different track than your DIP: interface A {} interface B : A {} interface C : A {} class X : B, C {} static assert(is(X : A)); void main() { A a = new C; // works, not sure if it's B.A or C.A } I know this is a different problem -- we aren't pointing at two different concrete implementations. -Steve
Oct 13 2014
Advantage of ky way is a more strictness then your way: if function with if(is(T: S)) will be called, error will be raised at the first trying of convert T to S. And we don't give the opportunity of possible error to spread away from the place of origin.
Oct 12 2014
Which will now create an error in the wrong place. IMO, the 'is' test should also fail. -SteveIn this case, you will see the real error and will able to fix if. For example call foo(c.a); Otherwice, you possible error will be fixed without taking into account your opinions.
Oct 10 2014
On 10/10/2014 10:09 AM, IgorStepanov wrote:I've created DIP for my pull request. DIP: http://wiki.dlang.org/DIP66 PR: https://github.com/D-Programming-Language/dmd/pull/3998 Please, comment it.Thanks, Igor!
Oct 10 2014
On 10/10/2014 10:09 AM, IgorStepanov wrote:Please, comment it.static assert(is(C : int)); //Ok, because C is subtype of int anyway.Comment should say that C is implicitly convertible to int struct Test1 { int a; int b; alias a this; alias b this; //Error: alias b this conflicts with alias a this; } DIP says this is "obviously incorrect", but what rule is being applied? I suspect the rule here is if typeof(a)==typeof(b), then it is rejected. What if typeof(a) is implicitly convertible to typeof(b), and vice-versa? Is alias this resolved before base class search, after base class search, or is it an error if both searches are successful? If 'a' and 'b' both contain overloads for function foo, then it should behave like imports do (which is a bit complex). Essentially, the rules for multiple alias this should be the same as for multiple imports and multiple mixin templates. These rules work, and the consistency will be expected.
Oct 10 2014
On 10/10/2014 11:25 PM, Walter Bright wrote:Essentially, the rules for multiple alias this should be the same as for multiple imports and multiple mixin templates. These rules work, and the consistency will be expected.Agreed. Do you suggest to overload alias this against imports and mixin templates?
Oct 10 2014
On 10/10/2014 3:06 PM, Timon Gehr wrote:On 10/10/2014 11:25 PM, Walter Bright wrote:I hadn't thought of that (thanks for bringing it up). My first thought is no. Alias this gets searched after those do, because it comes into play only when the symbol isn't resolved in the scope.Essentially, the rules for multiple alias this should be the same as for multiple imports and multiple mixin templates. These rules work, and the consistency will be expected.Agreed. Do you suggest to overload alias this against imports and mixin templates?
Oct 10 2014
On 10/11/2014 12:29 AM, Walter Bright wrote:On 10/10/2014 3:06 PM, Timon Gehr wrote:This allows for symbol hijacking (this is also the current behaviour): // --- module m; import std.stdio; // void foo(int x){ writeln("hi from m"); } // uncomment to hijack // --- module main; import std.stdio; struct T{ import m; alias s this; S s; } struct S{ void foo(int x){ writeln("hi from S"); } } void main(){ T t; t.foo(1); }On 10/10/2014 11:25 PM, Walter Bright wrote:I hadn't thought of that (thanks for bringing it up). My first thought is no. Alias this gets searched after those do, because it comes into play only when the symbol isn't resolved in the scope.Essentially, the rules for multiple alias this should be the same as for multiple imports and multiple mixin templates. These rules work, and the consistency will be expected.Agreed. Do you suggest to overload alias this against imports and mixin templates?
Oct 10 2014
On 10/10/2014 3:46 PM, Timon Gehr wrote:On 10/11/2014 12:29 AM, Walter Bright wrote:Hmm. Good point. The alias this should be done before imports.On 10/10/2014 3:06 PM, Timon Gehr wrote:This allows for symbol hijacking (this is also the current behaviour): // --- module m; import std.stdio; // void foo(int x){ writeln("hi from m"); } // uncomment to hijack // --- module main; import std.stdio; struct T{ import m; alias s this; S s; } struct S{ void foo(int x){ writeln("hi from S"); } } void main(){ T t; t.foo(1); }On 10/10/2014 11:25 PM, Walter Bright wrote:I hadn't thought of that (thanks for bringing it up). My first thought is no. Alias this gets searched after those do, because it comes into play only when the symbol isn't resolved in the scope.Essentially, the rules for multiple alias this should be the same as for multiple imports and multiple mixin templates. These rules work, and the consistency will be expected.Agreed. Do you suggest to overload alias this against imports and mixin templates?
Oct 10 2014
On Friday, 10 October 2014 at 22:51:34 UTC, Walter Bright wrote:On 10/10/2014 3:46 PM, Timon Gehr wrote:Symmetrically. You may use symbol from import, uncomment it in aliased type and hijack it.On 10/11/2014 12:29 AM, Walter Bright wrote:Hmm. Good point. The alias this should be done before imports.On 10/10/2014 3:06 PM, Timon Gehr wrote:This allows for symbol hijacking (this is also the current behaviour): // --- module m; import std.stdio; // void foo(int x){ writeln("hi from m"); } // uncomment to hijack // --- module main; import std.stdio; struct T{ import m; alias s this; S s; } struct S{ void foo(int x){ writeln("hi from S"); } } void main(){ T t; t.foo(1); }On 10/10/2014 11:25 PM, Walter Bright wrote:I hadn't thought of that (thanks for bringing it up). My first thought is no. Alias this gets searched after those do, because it comes into play only when the symbol isn't resolved in the scope.Essentially, the rules for multiple alias this should be the same as for multiple imports and multiple mixin templates. These rules work, and the consistency will be expected.Agreed. Do you suggest to overload alias this against imports and mixin templates?
Oct 10 2014
BTW. Overloaded functions in PR resolves un-properly (raises error even if can be resolved correct function) However it's easy to fix and I'll do it tomorrow.
Oct 10 2014
On Friday, 10 October 2014 at 21:25:17 UTC, Walter Bright wrote:On 10/10/2014 10:09 AM, IgorStepanov wrote:Not really. int i = C(); //conflict: c.a.i vs c.b.i (thus, C is not implicitly convertible to int)Please, comment it.static assert(is(C : int)); //Ok, because C is subtype of intanyway. Comment should say that C is implicitly convertible to intstruct Test1 { int a; int b; alias a this; alias b this; //Error: alias b this conflicts with alias a this; } DIP says this is "obviously incorrect", but what rule is being applied? I suspect the rule here is if typeof(a)==typeof(b), then it is rejected. What if typeof(a) is implicitly convertible to typeof(b), and vice-versa?In current state, if "typeof(a) is implicitly convertible to typeof(b), and vice-versa", compiler will accept this alias this declaration. However error may be raised at alias this resolving stage.Is alias this resolved before base class search, after base class search, or is it an error if both searches are successful?In existing alias this implementation alias this resolved after base class search. This DIP inherits it, thus now I suggest to check base classes before alias this. Is it acceptable? Should I add this into DIP?If 'a' and 'b' both contain overloads for function foo, then it should behave like imports do (which is a bit complex).Hmm. Now it works as I wrote it DIP pseudo-code: struct A { void foo(string); void foo(int); } struct B { void foo(double); } struct C { A a; B b; alias a this; alias b this; } C.foo("test"); //found only one acceptable foo: C.a.foo(string) C.foo(5); //1. Check a: found C.a.foo(int); //2. Check b: found C.b.foo(double); //3. Raise error: C.a.foo(int) vs C.b.foo(double) conflict C.foo(5.0); //found only one acceptable foo: C.b.foo(double) Is it Ok?Essentially, the rules for multiple alias this should be the same as for multiple imports and multiple mixin templates. These rules work, and the consistency will be expected.Where can I read about multiple mixin templates?
Oct 10 2014
On 10/11/2014 12:07 AM, IgorStepanov wrote:On Friday, 10 October 2014 at 21:25:17 UTC, Walter Bright wrote:The pseudo-code doesn't actually specify that the arguments the identifier is being called with are considered at all.If 'a' and 'b' both contain overloads for function foo, then it should behave like imports do (which is a bit complex).Hmm. Now it works as I wrote it DIP pseudo-code:struct A { void foo(string); void foo(int); } struct B { void foo(double); } struct C { A a; B b; alias a this; alias b this; } C.foo("test"); //found only one acceptable foo: C.a.foo(string) C.foo(5); //1. Check a: found C.a.foo(int); //2. Check b: found C.b.foo(double); //3. Raise error: C.a.foo(int) vs C.b.foo(double) conflict C.foo(5.0); //found only one acceptable foo: C.b.foo(double) Is it Ok? ...That is the right behaviour. What happens in this case: struct A{ void foo(int); void foo(double); } struct B void foo(string); } ... // (struct C and calls as yours) Is it correct that the DIP makes imports at aggregate scope shadow alias this lookups?
Oct 10 2014
On Friday, 10 October 2014 at 22:18:36 UTC, Timon Gehr wrote:On 10/11/2014 12:07 AM, IgorStepanov wrote:C.foo("test"); //Ok, C.b.foo(string); C.foo(5); //Ok, C.a.foo(int); C.foo(5.0); //Ok, C.a.foo(double); Compiler simply tries to forward c.foo(ARG) -> c.a.foo(ARG) and c.b.foo(ARG). If only one is correct, compiler will accept it. If both is correct, compiler will raise an error.On Friday, 10 October 2014 at 21:25:17 UTC, Walter Bright wrote:The pseudo-code doesn't actually specify that the arguments the identifier is being called with are considered at all.If 'a' and 'b' both contain overloads for function foo, then it should behave like imports do (which is a bit complex).Hmm. Now it works as I wrote it DIP pseudo-code:struct A { void foo(string); void foo(int); } struct B { void foo(double); } struct C { A a; B b; alias a this; alias b this; } C.foo("test"); //found only one acceptable foo: C.a.foo(string) C.foo(5); //1. Check a: found C.a.foo(int); //2. Check b: found C.b.foo(double); //3. Raise error: C.a.foo(int) vs C.b.foo(double) conflict C.foo(5.0); //found only one acceptable foo: C.b.foo(double) Is it Ok? ...That is the right behaviour. What happens in this case: struct A{ void foo(int); void foo(double); } struct B void foo(string); } ... // (struct C and calls as yours)
Oct 10 2014
On 10/10/2014 07:09 PM, IgorStepanov wrote:I've created DIP for my pull request. DIP: http://wiki.dlang.org/DIP66 PR: https://github.com/D-Programming-Language/dmd/pull/3998 Please, comment it.- "C c; int i = c; //Error: c.a.i vs c.b.i static assert(is(C : int)); //Ok, because C is subtype of int anyway." So now we can have 'subtypes' whose instances cannot be stored in variables of the 'base type'? Such behaviour is inconsistent with both the reference implementation and the documentation (and the two happen to be mutually inconsistent on how 'is(:)' should behave as well. :o) ) - "The following pseudo-code illustrates this: [...] Finally, if resultSet contains only one candidate, the compiler will accept it." This process might very well never terminate but it could terminate in more cases if it did something better than the naive brute-force search. I.e. either report cycles or don't keep exploring around cycles, but just looping indefinitely on cycles like the following is IMO not a good course of action: struct S{ alias get this; T get(){ return T.init; } } struct T{ alias get this; S get(){ return S.init; } int x; alias x this; } void main(){ S s; int x=s; } Furthermore, the following code compiles now, but doesn't under the approach described in the DIP. Is this an actual regression your pull introduces or is there a bug in the pseudocode?: class A{ alias x this; int x; } class B: A{ alias y this; int y; } void main(){ int x = new B(); } The same issue also needs to be considered if A and B are structs instead and B has an additional alias this to an A (the solution might also be part of a fix for the cycle issue). - "If resultSet contains more then one candidates, the compiler raises an error." Why? The language already has a way to deal with cross-scope overload resolution. (Also, what makes candidates different?)
Oct 10 2014
On Friday, 10 October 2014 at 22:05:18 UTC, Timon Gehr wrote:On 10/10/2014 07:09 PM, IgorStepanov wrote:C++ allowed subtypes, which can not be casted to the base type (inheritance of two identical, non-virtual base classes). Ok, I've wrote my position, understood your and wait the decision of the arbitrator:)I've created DIP for my pull request. DIP: http://wiki.dlang.org/DIP66 PR: https://github.com/D-Programming-Language/dmd/pull/3998 Please, comment it.- "C c; int i = c; //Error: c.a.i vs c.b.i static assert(is(C : int)); //Ok, because C is subtype of int anyway." So now we can have 'subtypes' whose instances cannot be stored in variables of the 'base type'?Such behaviour is inconsistent with both the reference implementation and the documentation (and the two happen to be mutually inconsistent on how 'is(:)' should behave as well. :o) ) - "The following pseudo-code illustrates this: [...] Finally, if resultSet contains only one candidate, the compiler will accept it." This process might very well never terminate but it could terminate in more cases if it did something better than the naive brute-force search. I.e. either report cycles or don't keep exploring around cycles, but just looping indefinitely on cycles like the following is IMO not a good course of action: struct S{ alias get this; T get(){ return T.init; } } struct T{ alias get this; S get(){ return S.init; } int x; alias x this; } void main(){ S s; int x=s; }This case described in DIP below. Recursion tree will be like: s.get s.get.get ->return, because T is already visited s.x -> winFurthermore, the following code compiles now, but doesn't under the approach described in the DIP. Is this an actual regression your pull introduces or is there a bug in the pseudocode?: class A{ alias x this; int x; } class B: A{ alias y this; int y; } void main(){ int x = new B(); } The same issue also needs to be considered if A and B are structs instead and B has an additional alias this to an A (the solution might also be part of a fix for the cycle issue). - "If resultSet contains more then one candidates, the compiler raises an error."struct A { short s; alias s this; } struct B { int i; alias i this; } struct C { A a; B b; alias a this; alias b this; } long l = C(); //What do you suggest?
Oct 10 2014
On 10/10/2014 3:20 PM, IgorStepanov wrote:The rule would be if: long l = C.a(); long l = C.b(); both compile, then: long l = C(); must be an error, even if one of C.a() or C.b() might be a "better" match. This is how things work for template mixins and imports.The same issue also needs to be considered if A and B are structs instead and B has an additional alias this to an A (the solution might also be part of a fix for the cycle issue). - "If resultSet contains more then one candidates, the compiler raises an error."struct A { short s; alias s this; } struct B { int i; alias i this; } struct C { A a; B b; alias a this; alias b this; } long l = C(); //What do you suggest?
Oct 10 2014
On Friday, 10 October 2014 at 22:50:25 UTC, Walter Bright wrote:On 10/10/2014 3:20 PM, IgorStepanov wrote:So it is.The rule would be if: long l = C.a(); long l = C.b(); both compile, then: long l = C(); must be an error, even if one of C.a() or C.b() might be a "better" match. This is how things work for template mixins and imports.The same issue also needs to be considered if A and B are structs instead and B has an additional alias this to an A (the solution might also be part of a fix for the cycle issue). - "If resultSet contains more then one candidates, the compiler raises an error."struct A { short s; alias s this; } struct B { int i; alias i this; } struct C { A a; B b; alias a this; alias b this; } long l = C(); //What do you suggest?
Oct 10 2014
On 10/10/2014 4:23 PM, IgorStepanov wrote:On Friday, 10 October 2014 at 22:50:25 UTC, Walter Bright wrote:Good! The same rule applies for overloading.must be an error, even if one of C.a() or C.b() might be a "better" match. This is how things work for template mixins and imports.So it is.
Oct 10 2014
On Saturday, 11 October 2014 at 00:00:48 UTC, Walter Bright wrote:On 10/10/2014 4:23 PM, IgorStepanov wrote:I've implemented overloading: https://github.com/D-Programming-Language/dmd/pull/3998/files#diff-17b22eae29e74ce6ec29037438b5031cR2136 Please, tell me, what changes should I make to the DIP as a result of yesterday's discussions. And please, tell your opinion about "is" issue: class A { int i; alias i this; } class B { int i; alias i this; } class C { A a; B b; alias a this; alias b this; } void foo(T)(T arg) if(is(T : int)) { ... } foo(C()); //Should it pass or not?On Friday, 10 October 2014 at 22:50:25 UTC, Walter Bright wrote:Good! The same rule applies for overloading.must be an error, even if one of C.a() or C.b() might be a "better" match. This is how things work for template mixins and imports.So it is.
Oct 11 2014
On 10/11/2014 7:23 AM, IgorStepanov wrote:On Saturday, 11 October 2014 at 00:00:48 UTC, Walter Bright wrote:At the very least, it should say it resolves ambiguities the same way that imports and template mixins do.On 10/10/2014 4:23 PM, IgorStepanov wrote:I've implemented overloading: https://github.com/D-Programming-Language/dmd/pull/3998/files#diff-17b22eae29e74ce6ec29037438b5031cR2136 Please, tell me, what changes should I make to the DIP as a result of yesterday's discussions.On Friday, 10 October 2014 at 22:50:25 UTC, Walter Bright wrote:Good! The same rule applies for overloading.must be an error, even if one of C.a() or C.b() might be a "better" match. This is how things work for template mixins and imports.So it is.And please, tell your opinion about "is" issue: class A { int i; alias i this; } class B { int i; alias i this; } class C { A a; B b; alias a this; alias b this; } void foo(T)(T arg) if(is(T : int)) { ... } foo(C()); //Should it pass or not?There's a rule with imports that if the same symbol is reachable via multiple paths through the imports, that it is not an ambiguity error. Here, the same type is reachable through multiple alias this paths, so by analogy it shouldn't be an error.
Oct 11 2014
On Sunday, 12 October 2014 at 04:31:22 UTC, Walter Bright wrote:On 10/11/2014 7:23 AM, IgorStepanov wrote:It's the same type, but different symbols; actual accesses would be ambiguous. `is(T : int)` shouldn't evaluate to true if `int a = T.init;` would fail.class A { int i; alias i this; } class B { int i; alias i this; } class C { A a; B b; alias a this; alias b this; } void foo(T)(T arg) if(is(T : int)) { ... } foo(C()); //Should it pass or not?There's a rule with imports that if the same symbol is reachable via multiple paths through the imports, that it is not an ambiguity error. Here, the same type is reachable through multiple alias this paths, so by analogy it shouldn't be an error.
Oct 12 2014
On Sunday, 12 October 2014 at 08:36:05 UTC, Marc Schütz wrote:On Sunday, 12 October 2014 at 04:31:22 UTC, Walter Bright wrote:I found an example of a situation that is bothering me. Let we have a persistence framework, which provides a storing D object in some persistence storage: DB, file et c. In introduces paired functions store/load and special type PersistenceObject. If stored type is subtype of PersistenceObject it converts to PersistenceObject and PersistenceObject.load(stream) called for loading object (and PersistenceObject.store(stream) for storing). Otherwice if object can't be converted to PersistenceObject it should be serialized via "serialize" function (or deserialized via "deserialize"). struct PersistenceFramework { void store(T)(T arg) if (is(T : PersistenceObject)) { PersistenceObject po = arg; arg.store(stream); } void store(T)(T arg) if (!is(T : PersistenceObject)) { PersistenceObject po = arg; store(serialize(arg)); } void load(T)(ref T arg) if (is(T : PersistenceObject)) { PersistenceObject po = arg; arg.load(stream); } void load(T)(ref T arg) if (!is(T : PersistenceObject)) { PersistenceObject po = arg; load(serialize(arg)); } Stream stream; } /**************************************************************** And we have the next types which we want to store and load *****************************************************************/ struct Role { ... } struct User { Role role; PersistenceObject po; //... alias role this; alias po this; } /*****************************************************************/ User u; persistenceFramework.load(u) //... persistenceFramework.store(u); /******************************************************************/ Role is not subtype of PersistenceObject thus all works ok. We can store User via User.po and load it again; Some time later, Role designer decided that Role should be subtype of PersistenceObject and changed Role definition: struct Role { ... PersistenceObject po; alias po this; } Now, User can not be converted to PersistenceObject because there are two path to convert: User.po and User.role.po; Storing code after this change will be copiled successfully (if we follow your "is" rule), however object will be tried to load via "void load(T)(ref T arg) if (!is(T : PersistenceObject))". Because object was saved via "void store(T)(T arg) if (is(T : PersistenceObject))" at the previous program run, user will not be loaded succesfully. Moreover, you will get an strange unexpected program behaviour and will be hard to find real error cause. /*****************************************************************/ And finally, if you want to check, if you Type _really_ can be converted to AnotherType, you can use the next check: void foo(Type)(Type arg) if (is(typeof({AnotherType x = Type.init;}))) { }On 10/11/2014 7:23 AM, IgorStepanov wrote:It's the same type, but different symbols; actual accesses would be ambiguous. `is(T : int)` shouldn't evaluate to true if `int a = T.init;` would fail.class A { int i; alias i this; } class B { int i; alias i this; } class C { A a; B b; alias a this; alias b this; } void foo(T)(T arg) if(is(T : int)) { ... } foo(C()); //Should it pass or not?There's a rule with imports that if the same symbol is reachable via multiple paths through the imports, that it is not an ambiguity error. Here, the same type is reachable through multiple alias this paths, so by analogy it shouldn't be an error.
Oct 12 2014
My preferred solution would be to reject the 2nd alias declaration outright. I don't see any value in intentionally creating the above pattern, _if_ it occurs then it's most likely due to an unintentional side-effect of a re-factoring, thus it should error out as close as possible to the real error.On 10/11/2014 7:23 AM, IgorStepanov wrote:class A { int i; alias i this; } class B { int i; alias i this; } class C { A a; B b; alias a this; alias b this; }
Oct 13 2014
On Monday, 13 October 2014 at 15:21:32 UTC, Daniel N wrote:This code tell that C is subtype of A and C is subtype of B. User can use this fact in his code: void foo(B); C c = new C; foo(c); //Ok. Of course, we shouldn't allow user to cast c to int: int i = c; //wrong However, user can explicitly cast c to his subtype, which is convertable to int: int i = cast(B)c; //Ok Summarizing, I disagree with suggestion disallow this code at type semantic stage.My preferred solution would be to reject the 2nd alias declaration outright. I don't see any value in intentionally creating the above pattern, _if_ it occurs then it's most likely due to an unintentional side-effect of a re-factoring, thus it should error out as close as possible to the real error.On 10/11/2014 7:23 AM, IgorStepanov wrote:class A { int i; alias i this; } class B { int i; alias i this; } class C { A a; B b; alias a this; alias b this; }
Oct 14 2014
On Tuesday, 14 October 2014 at 12:33:50 UTC, IgorStepanov wrote:This code tell that C is subtype of A and C is subtype of B. User can use this fact in his code: void foo(B); C c = new C; foo(c); //Ok. Of course, we shouldn't allow user to cast c to int: int i = c; //wrong However, user can explicitly cast c to his subtype, which is convertable to int: int i = cast(B)c; //Ok Summarizing, I disagree with suggestion disallow this code at type semantic stage.I agree. It will also make possible to break already working disambugation of `foo(c)` kind but adding new `alias this` to one of subtypes independently. That sounds annoying.
Oct 14 2014
On Wednesday, 15 October 2014 at 02:46:05 UTC, Dicebot wrote:On Tuesday, 14 October 2014 at 12:33:50 UTC, IgorStepanov wrote:I guess the best part of D is, you have the means to fix anything you disagree with yourself... I can add a static assert to my class and be happy. I have another idea, we could define that the shortest conversion chain wins, analogous to type promotions, that makes it possible to contain the issue inside C. class C { A a; B b; int disambiguate_int() { return a; } alias a this; alias b this; alias disambiguate_int this; static assert(__traits(compiles, {int _ = C.init;}), "Ambiguous alias this"); } i.e. this assert should pass.This code tell that C is subtype of A and C is subtype of B. User can use this fact in his code: void foo(B); C c = new C; foo(c); //Ok. Of course, we shouldn't allow user to cast c to int: int i = c; //wrong However, user can explicitly cast c to his subtype, which is convertable to int: int i = cast(B)c; //Ok Summarizing, I disagree with suggestion disallow this code at type semantic stage.I agree. It will also make possible to break already working disambugation of `foo(c)` kind but adding new `alias this` to one of subtypes independently. That sounds annoying.
Oct 14 2014
On Wednesday, 15 October 2014 at 03:49:41 UTC, Daniel N wrote:On Wednesday, 15 October 2014 at 02:46:05 UTC, Dicebot wrote:In first edition I've implemented rule, when if type defines alias this directly, this alias hides all indirect aliases with the same type. However Andrey said that we should implement the strictest rules as possible and maybe relax them later. Thus I implemented current rules, but saved the old implemetation of search. After some time we will able to return to first rule. It's not hard.On Tuesday, 14 October 2014 at 12:33:50 UTC, IgorStepanov wrote:I guess the best part of D is, you have the means to fix anything you disagree with yourself... I can add a static assert to my class and be happy. I have another idea, we could define that the shortest conversion chain wins, analogous to type promotions, that makes it possible to contain the issue inside C. class C { A a; B b; int disambiguate_int() { return a; } alias a this; alias b this; alias disambiguate_int this; static assert(__traits(compiles, {int _ = C.init;}), "Ambiguous alias this"); } i.e. this assert should pass.This code tell that C is subtype of A and C is subtype of B. User can use this fact in his code: void foo(B); C c = new C; foo(c); //Ok. Of course, we shouldn't allow user to cast c to int: int i = c; //wrong However, user can explicitly cast c to his subtype, which is convertable to int: int i = cast(B)c; //Ok Summarizing, I disagree with suggestion disallow this code at type semantic stage.I agree. It will also make possible to break already working disambugation of `foo(c)` kind but adding new `alias this` to one of subtypes independently. That sounds annoying.
Oct 15 2014
On Sunday, 19 October 2014 at 21:00:29 UTC, IgorStepanov wrote:Bump.For me current description and PR look solid and safe enough to try.
Oct 21 2014
On Tuesday, 21 October 2014 at 08:17:19 UTC, Dicebot wrote:On Sunday, 19 October 2014 at 21:00:29 UTC, IgorStepanov wrote:We are waiting for an Andrey's Word. Walter, as I understand haven't unresolved objections.Bump.For me current description and PR look solid and safe enough to try.
Oct 21 2014
On 10/21/14 1:24 PM, IgorStepanov wrote:On Tuesday, 21 October 2014 at 08:17:19 UTC, Dicebot wrote:There are issues with the proposal. I must get to them today. -- AndreiOn Sunday, 19 October 2014 at 21:00:29 UTC, IgorStepanov wrote:We are waiting for an Andrey's Word. Walter, as I understand haven't unresolved objections.Bump.For me current description and PR look solid and safe enough to try.
Oct 27 2014
On 10/19/14 2:00 PM, IgorStepanov wrote:Bump.I've made a few grammar and fluency edits to the DIP, and collected a few thoughts while doing that. Will get back on this before too long. -- Andrei
Oct 23 2014
On Friday, 24 October 2014 at 06:04:24 UTC, Andrei Alexandrescu wrote:On 10/19/14 2:00 PM, IgorStepanov wrote:I've seen it. Thanks! Waiting for a comments. Should I add chapter about method overloading with alias this: it should work (and works) as cross-module overloading. It should imply This implies from the DIP but hasn't written explicitly. OT: Should `et\s?c\.?` be written as "etc" in English? I thought that it should be written as "et c.", because "et cetera". Or is it an anachronism?Bump.I've made a few grammar and fluency edits to the DIP, and collected a few thoughts while doing that. Will get back on this before too long. -- Andrei
Oct 24 2014
On Friday, 24 October 2014 at 13:05:54 UTC, IgorStepanov wrote:On Friday, 24 October 2014 at 06:04:24 UTC, Andrei Alexandrescu wrote:The convention is to write "etc.", with the period indicating that the rest of the word has been omitted. If it appears in the middle of a sentence, I don't capitalize the subsequent word as it doesn't really make sense, but I'm not sure what the actual convention is in that respect.On 10/19/14 2:00 PM, IgorStepanov wrote:I've seen it. Thanks! Waiting for a comments. Should I add chapter about method overloading with alias this: it should work (and works) as cross-module overloading. It should imply This implies from the DIP but hasn't written explicitly. OT: Should `et\s?c\.?` be written as "etc" in English? I thought that it should be written as "et c.", because "et cetera". Or is it an anachronism?Bump.I've made a few grammar and fluency edits to the DIP, and collected a few thoughts while doing that. Will get back on this before too long. -- Andrei
Oct 24 2014
On Friday, 24 October 2014 at 13:17:28 UTC, Meta wrote:On Friday, 24 October 2014 at 13:05:54 UTC, IgorStepanov wrote:A full stop (a.k.a. period in some countries) for abbreviation does not imply that the following word must be capitalised. Sentences must start with a capital.On Friday, 24 October 2014 at 06:04:24 UTC, Andrei Alexandrescu wrote:The convention is to write "etc.", with the period indicating that the rest of the word has been omitted. If it appears in the middle of a sentence, I don't capitalize the subsequent word as it doesn't really make sense, but I'm not sure what the actual convention is in that respect.On 10/19/14 2:00 PM, IgorStepanov wrote:I've seen it. Thanks! Waiting for a comments. Should I add chapter about method overloading with alias this: it should work (and works) as cross-module overloading. It should imply This implies from the DIP but hasn't written explicitly. OT: Should `et\s?c\.?` be written as "etc" in English? I thought that it should be written as "et c.", because "et cetera". Or is it an anachronism?Bump.I've made a few grammar and fluency edits to the DIP, and collected a few thoughts while doing that. Will get back on this before too long. -- Andrei
Oct 24 2014
On Friday, 24 October 2014 at 13:17:28 UTC, Meta wrote:On Friday, 24 October 2014 at 13:05:54 UTC, IgorStepanov wrote:Thanks for the explanation:)On Friday, 24 October 2014 at 06:04:24 UTC, Andrei Alexandrescu wrote:The convention is to write "etc.", with the period indicating that the rest of the word has been omitted. If it appears in the middle of a sentence, I don't capitalize the subsequent word as it doesn't really make sense, but I'm not sure what the actual convention is in that respect.On 10/19/14 2:00 PM, IgorStepanov wrote:I've seen it. Thanks! Waiting for a comments. Should I add chapter about method overloading with alias this: it should work (and works) as cross-module overloading. It should imply This implies from the DIP but hasn't written explicitly. OT: Should `et\s?c\.?` be written as "etc" in English? I thought that it should be written as "et c.", because "et cetera". Or is it an anachronism?Bump.I've made a few grammar and fluency edits to the DIP, and collected a few thoughts while doing that. Will get back on this before too long. -- Andrei
Oct 24 2014
On 10/24/14 6:05 AM, IgorStepanov wrote:On Friday, 24 October 2014 at 06:04:24 UTC, Andrei Alexandrescu wrote:Coming soon. I've been under quite a bit of pressure as of late.On 10/19/14 2:00 PM, IgorStepanov wrote:I've seen it. Thanks! Waiting for a comments.Bump.I've made a few grammar and fluency edits to the DIP, and collected a few thoughts while doing that. Will get back on this before too long. -- AndreiShould I add chapter about method overloading with alias this: it should work (and works) as cross-module overloading. It should imply This implies from the DIP but hasn't written explicitly.Interesting. I think it should work like overloading of calls in base and derived classes.OT: Should `et\s?c\.?` be written as "etc" in English? I thought that it should be written as "et c.", because "et cetera". Or is it an anachronism?You can't go wrong with M-W: http://www.merriam-webster.com/dictionary/etc Andrei
Oct 27 2014
On Tuesday, 28 October 2014 at 02:07:23 UTC, Andrei Alexandrescu wrote:On 10/24/14 6:05 AM, IgorStepanov wrote:Not really. Rules which define overloading class methods doesn't describe multiple inheritance case. In single inheritance case alias this rule is similar with inheritance rule: derived overload set hides base base overload set: struct A { void foo(string) { writeln("string"); } void foo(int) { writeln("int"); } } struct B { void foo(double) { writeln("double"); } A a; alias a this; } B b; b.foo("string"); //error b.foo(42); //called B.foo(double), not B.a.foo(int); The second test is not similar to inherintance rules, but this case is not relevant with multiple alias this and it is already done. When I said "cross-module overloading", I told about case when C inherits (via alias this) A and B, both A and B have "foo" methods with different paramethers and compiler should resolve foo call: struct A { void foo(string) { writeln("string"); } void foo(int) { writeln("int"); } } struct B { void foo(double) { writeln("double"); } } struct C { A a; B b; alias a this; alias b this; } C c; c.foo("str"); // OK, c.a.foo(string) c.foo(4.2); //OK, c.b.foo(double); c.foo(42); //Error: c.a.foo(int) or c.b.foo(double)? BTW, similar case with multiple inheritance via interfaces works absolutely incorrect: interface CA { final void foo(string) { writeln("string"); } final void foo(int) { writeln("int"); } } interface CB { final void foo(double) { writeln("double"); } } class CC : CA, CB { } auto cc = new CC(); cc.foo("xxx"); //OK, called CA.foo(string) cc.foo(42); //called CA.foo(int) without any warnings cc.foo(4.2); //Error: unable to call CA.foo with double argument. In other words, compiler choses the first base interface, uses its overload set and ignores other interfaces.On Friday, 24 October 2014 at 06:04:24 UTC, Andrei Alexandrescu wrote:Coming soon. I've been under quite a bit of pressure as of late.On 10/19/14 2:00 PM, IgorStepanov wrote:I've seen it. Thanks! Waiting for a comments.Bump.I've made a few grammar and fluency edits to the DIP, and collected a few thoughts while doing that. Will get back on this before too long. -- AndreiShould I add chapter about method overloading with alias this: it should work (and works) as cross-module overloading. It should imply This implies from the DIP but hasn't written explicitly.Interesting. I think it should work like overloading of calls in base and derived classes.Thanks.OT: Should `et\s?c\.?` be written as "etc" in English? I thought that it should be written as "et c.", because "et cetera". Or is it an anachronism?You can't go wrong with M-W: http://www.merriam-webster.com/dictionary/etc
Oct 28 2014
On Wednesday, 15 October 2014 at 09:50:17 UTC, IgorStepanov wrote:In first edition I've implemented rule, when if type defines alias this directly, this alias hides all indirect aliases with the same type. However Andrey said that we should implement the strictest rules as possible and maybe relax them later. Thus I implemented current rules, but saved the old implemetation of search. After some time we will able to return to first rule. It's not hard.I see, in order to prevent any accidental shadowing, maybe one can consider "override alias this", if we decide to make a relaxed version in the future?
Oct 19 2014
On Monday, 20 October 2014 at 00:23:46 UTC, Daniel N wrote:On Wednesday, 15 October 2014 at 09:50:17 UTC, IgorStepanov wrote:Make sense. I think we should postpone but not forgotten this feature. When main part will be merged, we will able to start discussion about override alias this. What about the other features?In first edition I've implemented rule, when if type defines alias this directly, this alias hides all indirect aliases with the same type. However Andrey said that we should implement the strictest rules as possible and maybe relax them later. Thus I implemented current rules, but saved the old implemetation of search. After some time we will able to return to first rule. It's not hard.I see, in order to prevent any accidental shadowing, maybe one can consider "override alias this", if we decide to make a relaxed version in the future?
Oct 19 2014
On 10/10/14 19:09, IgorStepanov via Digitalmars-d wrote:I've created DIP for my pull request. DIP: http://wiki.dlang.org/DIP66 PR: https://github.com/D-Programming-Language/dmd/pull/3998 Please, comment it.This may be beyond the scope of the DIP, but is there any intention (or any need?) to set rules for how alias this should behave in the case of different protection levels for the base type and the alias? I ask because there is a known issue related to this: https://issues.dlang.org/show_bug.cgi?id=10996 ... but also because any rules set for this, might in principle affect the desirable priority rules for multiple alias this too.
Oct 10 2014
On 10/10/2014 3:27 PM, Joseph Rushton Wakeling via Digitalmars-d wrote:On 10/10/14 19:09, IgorStepanov via Digitalmars-d wrote:I like the C++ rule that says that access control is not considered for name lookup. I know it makes for some annoying results, but the simplicity of the rule makes it much more understandable.I've created DIP for my pull request. DIP: http://wiki.dlang.org/DIP66 PR: https://github.com/D-Programming-Language/dmd/pull/3998 Please, comment it.This may be beyond the scope of the DIP, but is there any intention (or any need?) to set rules for how alias this should behave in the case of different protection levels for the base type and the alias?I ask because there is a known issue related to this: https://issues.dlang.org/show_bug.cgi?id=10996 ... but also because any rules set for this, might in principle affect the desirable priority rules for multiple alias this too.
Oct 10 2014
On 2014-10-11 00:52, Walter Bright wrote:I like the C++ rule that says that access control is not considered for name lookup. I know it makes for some annoying results, but the simplicity of the rule makes it much more understandable.I'm not so sure about that. Perhaps it makes it more understandable for a language designer. But not for a user. You try to call a function but you get a conflict with a private symbol. The user will get frustrated thinking: "stupid compiler, of course I want to call the public function". -- /Jacob Carlborg
Oct 11 2014
On 10/11/2014 3:42 AM, Jacob Carlborg wrote:On 2014-10-11 00:52, Walter Bright wrote:The theory is that simpler rules are better than complex rules, even if the simpler rules aren't always ideal.I like the C++ rule that says that access control is not considered for name lookup. I know it makes for some annoying results, but the simplicity of the rule makes it much more understandable.I'm not so sure about that. Perhaps it makes it more understandable for a language designer. But not for a user. You try to call a function but you get a conflict with a private symbol. The user will get frustrated thinking: "stupid compiler, of course I want to call the public function".
Oct 11 2014
On 10/12/2014 06:28 AM, Walter Bright wrote:On 10/11/2014 3:42 AM, Jacob Carlborg wrote:Public symbols conflicting with private symbols are not just not ideal, they are a major PITA. The procedure for resolving ambiguities using alias introduces new private symbols itself!On 2014-10-11 00:52, Walter Bright wrote:The theory is that simpler rules are better than complex rules, even if the simpler rules aren't always ideal.I like the C++ rule that says that access control is not considered for name lookup. I know it makes for some annoying results, but the simplicity of the rule makes it much more understandable.I'm not so sure about that. Perhaps it makes it more understandable for a language designer. But not for a user. You try to call a function but you get a conflict with a private symbol. The user will get frustrated thinking: "stupid compiler, of course I want to call the public function".
Oct 12 2014
On 11/10/14 00:52, Walter Bright via Digitalmars-d wrote:I like the C++ rule that says that access control is not considered for name lookup. I know it makes for some annoying results, but the simplicity of the rule makes it much more understandable.That's fine. I just wanted to be sure that there wasn't a risk of multiple alias this breaking in unpleasant ways, if/when https://issues.dlang.org/show_bug.cgi?id=10996 is fixed.
Oct 12 2014
On 10/10/14 10:09 AM, IgorStepanov wrote:I've created DIP for my pull request. DIP: http://wiki.dlang.org/DIP66 PR: https://github.com/D-Programming-Language/dmd/pull/3998 Please, comment it.Here's my destruction: * "symbol can be a field or a get-property (method annotated with property and taking zero parameters)." -> actually: (a) the property annotation is not necessary (b) there may be one ore more parameters so long as they're all defaulted So the text should be "obj.symbol must be a valid expression". * "At the AliasThis declaration semantic stage, the compiler can perform the initial checks and reject the obviously incorrect AliasThis declarations." -> it might be simpler (for the sake of simplifying generic code) to just delay all error checking to the first use. * I don't think the pseudocode helps a lot. Better let's have a clear and precise specification (I've edited the lookup order into an ordered list). * Regarding the lookup, opDispatch shouldn't come before alias this, or should come before base class lookup. Essentially alias this is subtyping so it should enjoy similar privileges to base classes. A different way to look at it is opDispatch is a "last resort" lookup mechanism, just one step above the UFCS lowering. * The DIP should specify the working of alias this as rewrites/lowerings, not pseudocode. Basically for each kth declaration "alias symbolk this;" the compiler rewrites "obj.xyz" as "obj.symbolk.xyz" and then does the usual lookup on that expression. That means the whole algorithms is applied again etc. If more than one rewrite typechecks, that's an ambiguity error. * IMPORTANT: The DIP must discuss rvalue vs. lvalue cases. The rewrite approach simplifies that discussion because it's clear what happens by simply reasoning about the rewritten expression. Lvalue vs. rvalue matters a lot practically. Consider: struct A { private int x; alias x this; } struct B { private int _x; int x() { return x; } alias x this; } Then x can be passed by reference, modified directly etc. for A but not for B. =========== Congratulations on taking this to a DIP. It clarifies things really nice and it's an example to follow for future language changes. Andrei
Oct 28 2014
On Tuesday, 28 October 2014 at 19:45:09 UTC, Andrei Alexandrescu wrote:On 10/10/14 10:09 AM, IgorStepanov wrote:Thanks for answer, I hope, I'll able to to carefully consider your comments tomorrow. Now I want to ask about the one thing. What do you think about compatibility with existing alias this implementation? For example you wrote: "Regarding the lookup, opDispatch shouldn't come before alias this, or should come before base class lookup.". This requirement breaks the existing code. We can apply this change in DIP, however if we want to apply this change to compiler, we should be careful. Moreover, I don't see the way to create deprecation path: old implementation->deprecated old implementation & new inmplementation -> prohibited old implementation & new inmplementation. If we will change the semantic order of proprerty resolving, we will not able to warn user about changes. Suddenly his code will be compiled in a different way. And please comment my way to resolving "is" expression via alias-this: http://forum.dlang.org/thread/ubafmwvxwtolhmnxbrsf forum.dlang.org?page=5 Thanks for the DIP review.I've created DIP for my pull request. DIP: http://wiki.dlang.org/DIP66 PR: https://github.com/D-Programming-Language/dmd/pull/3998 Please, comment it.Here's my destruction: * "symbol can be a field or a get-property (method annotated with property and taking zero parameters)." -> actually: (a) the property annotation is not necessary (b) there may be one ore more parameters so long as they're all defaulted So the text should be "obj.symbol must be a valid expression". * "At the AliasThis declaration semantic stage, the compiler can perform the initial checks and reject the obviously incorrect AliasThis declarations." -> it might be simpler (for the sake of simplifying generic code) to just delay all error checking to the first use. * I don't think the pseudocode helps a lot. Better let's have a clear and precise specification (I've edited the lookup order into an ordered list). * Regarding the lookup, opDispatch shouldn't come before alias this, or should come before base class lookup. Essentially alias this is subtyping so it should enjoy similar privileges to base classes. A different way to look at it is opDispatch is a "last resort" lookup mechanism, just one step above the UFCS lowering. * The DIP should specify the working of alias this as rewrites/lowerings, not pseudocode. Basically for each kth declaration "alias symbolk this;" the compiler rewrites "obj.xyz" as "obj.symbolk.xyz" and then does the usual lookup on that expression. That means the whole algorithms is applied again etc. If more than one rewrite typechecks, that's an ambiguity error. * IMPORTANT: The DIP must discuss rvalue vs. lvalue cases. The rewrite approach simplifies that discussion because it's clear what happens by simply reasoning about the rewritten expression. Lvalue vs. rvalue matters a lot practically. Consider: struct A { private int x; alias x this; } struct B { private int _x; int x() { return x; } alias x this; } Then x can be passed by reference, modified directly etc. for A but not for B. =========== Congratulations on taking this to a DIP. It clarifies things really nice and it's an example to follow for future language changes. Andrei
Oct 28 2014
On Tuesday, 28 October 2014 at 20:09:07 UTC, IgorStepanov wrote:And please comment my way to resolving "is" expression via alias-this: http://forum.dlang.org/thread/ubafmwvxwtolhmnxbrsf forum.dlang.org?page=5Something else related to the discussion about `is` from this thread: http://forum.dlang.org/post/tulvmydnogbgebnxybfk forum.dlang.org. The following code: import std.math; import std.traits; struct S(T) if(isFloatingPoint!T) { T val; alias val this; } void main() { auto s = S!float(); assert(isNaN(s)); s = 10.0; assert(!isNaN(s)); } Current fails to compile with this error: Error: template std.math.isNaN cannot deduce function from argument types !()(S!float), candidates are: std/math.d(4171): std.math.isNaN(X)(X x) if (isFloatingPoint!X) Is this a problem with the current implementation of `alias this`, or should isFloatingPoint be changed so that it also accepts types that alias a floating point type?
Oct 28 2014
On Tuesday, 28 October 2014 at 21:55:35 UTC, Meta wrote:or should isFloatingPoint be changed so that it also accepts types that alias a floating point type?My mistake, I mean isNaN and similar functions, such as isNumeric.
Oct 28 2014
On Tuesday, 28 October 2014 at 21:55:35 UTC, Meta wrote:On Tuesday, 28 October 2014 at 20:09:07 UTC, IgorStepanov wrote:You may see isFloatingPoint declaration in traits.d: enum bool isFloatingPoint(T) = is(FloatingPointTypeOf!T) && !isAggregateType!T; This template explicitly says that T shouldn't be an aggregate type. Thus std.math.isNaN(X)(X x) if (isFloatingPoint!X) shouldn't accept a struct.And please comment my way to resolving "is" expression via alias-this: http://forum.dlang.org/thread/ubafmwvxwtolhmnxbrsf forum.dlang.org?page=5Something else related to the discussion about `is` from this thread: http://forum.dlang.org/post/tulvmydnogbgebnxybfk forum.dlang.org. The following code: import std.math; import std.traits; struct S(T) if(isFloatingPoint!T) { T val; alias val this; } void main() { auto s = S!float(); assert(isNaN(s)); s = 10.0; assert(!isNaN(s)); } Current fails to compile with this error: Error: template std.math.isNaN cannot deduce function from argument types !()(S!float), candidates are: std/math.d(4171): std.math.isNaN(X)(X x) if (isFloatingPoint!X) Is this a problem with the current implementation of `alias this`, or should isFloatingPoint be changed so that it also accepts types that alias a floating point type?
Oct 28 2014
On Tuesday, 28 October 2014 at 22:55:24 UTC, IgorStepanov wrote:You may see isFloatingPoint declaration in traits.d: enum bool isFloatingPoint(T) = is(FloatingPointTypeOf!T) && !isAggregateType!T; This template explicitly says that T shouldn't be an aggregate type. Thus std.math.isNaN(X)(X x) if (isFloatingPoint!X) shouldn't accept a struct.Although alias this is supposed to denote subtyping, here is a violation of the Liskov Substitution Principle; although S is a subtype of float, there are some cases where it's invalid to substitute an S for a float. This seems like a problem with alias this to me. As S is aliased to float, typeof(s.val) should be passed to isFloatingPoint if passing S fails.
Oct 28 2014
On Tuesday, 28 October 2014 at 23:12:21 UTC, Meta wrote:On Tuesday, 28 October 2014 at 22:55:24 UTC, IgorStepanov wrote:Your issue is not relevant with alias this implementation. isFloatingPoint is a library implemented trait, which uses compile-time reflections to for verifying the truth of the approval "T is floating point type". If you think that isFloatingPoint implemented incorrectly, you may start corresponding discussion. Otherwice, if you think that std.math.isNaN should accept user types which may be converted to floating point type, you may discuss that. If you want simply solve you problem you may define own auto isNaN(T)(S!(T) arg) { return isNaN(cast(T)arg); }You may see isFloatingPoint declaration in traits.d: enum bool isFloatingPoint(T) = is(FloatingPointTypeOf!T) && !isAggregateType!T; This template explicitly says that T shouldn't be an aggregate type. Thus std.math.isNaN(X)(X x) if (isFloatingPoint!X) shouldn't accept a struct.Although alias this is supposed to denote subtyping, here is a violation of the Liskov Substitution Principle; although S is a subtype of float, there are some cases where it's invalid to substitute an S for a float. This seems like a problem with alias this to me. As S is aliased to float, typeof(s.val) should be passed to isFloatingPoint if passing S fails.
Oct 29 2014
You should rethink implementing multiple alias this. D is increasingly becoming a poorly typed language. "alias this" is basically static prototype-based programming. http://en.wikipedia.org/wiki/Prototype-based_programming Self had multiple inheritance based on prototypes and removed it because it was not much used and lead to problems when figuring out which methods were called.
Oct 28 2014
On Tuesday, 28 October 2014 at 22:58:53 UTC, Ola Fosheim Grøstad wrote:You should rethink implementing multiple alias this. D is increasingly becoming a poorly typed language. "alias this" is basically static prototype-based programming. http://en.wikipedia.org/wiki/Prototype-based_programming Self had multiple inheritance based on prototypes and removed it because it was not much used and lead to problems when figuring out which methods were called.No. D is as poorly typed as one wants is to be and multiple alias this is a necessary tool to achieve strong static typing without sacrificing expressiveness.
Oct 31 2014
On Friday, 10 October 2014 at 17:09:08 UTC, IgorStepanov wrote:I've created DIP for my pull request. DIP: http://wiki.dlang.org/DIP66 PR: https://github.com/D-Programming-Language/dmd/pull/3998 Please, comment it.Well, nearly 3 years later and nothing!
Jun 04 2017
On Friday, 10 October 2014 at 17:09:08 UTC, IgorStepanov wrote:I've created DIP for my pull request. DIP: http://wiki.dlang.org/DIP66 PR: https://github.com/D-Programming-Language/dmd/pull/3998 Please, comment it.What's the state?
Mar 20 2019
On Wednesday, 20 March 2019 at 21:39:48 UTC, sighoya wrote:On Friday, 10 October 2014 at 17:09:08 UTC, IgorStepanov wrote:https://github.com/dlang/dmd/pull/8378 It's waiting on someone willing to work with reviewers to refactor it and integrate it into the codebase to reviewers' satisfaction. MikeI've created DIP for my pull request. DIP: http://wiki.dlang.org/DIP66 PR: https://github.com/D-Programming-Language/dmd/pull/3998 Please, comment it.What's the state?
Mar 20 2019
On Wednesday, 20 March 2019 at 21:50:55 UTC, Mike Franklin wrote:On Wednesday, 20 March 2019 at 21:39:48 UTC, sighoya wrote:How can I help if I'm not the one creating the PR?On Friday, 10 October 2014 at 17:09:08 UTC, IgorStepanov wrote:https://github.com/dlang/dmd/pull/8378 It's waiting on someone willing to work with reviewers to refactor it and integrate it into the codebase to reviewers' satisfaction. MikeI've created DIP for my pull request. DIP: http://wiki.dlang.org/DIP66 PR: https://github.com/D-Programming-Language/dmd/pull/3998 Please, comment it.What's the state?
Mar 20 2019
On Wednesday, 20 March 2019 at 21:58:46 UTC, sighoya wrote:How can I help if I'm not the one creating the PR?It needs someone willing to adopt the PR and work with reviewers to get it across the finish line. If you've never worked on DMD before, cloning the DMD, druntime, Phobos, etc. and learning how to build the compiler and run the test suite locally is the first step. Mike
Mar 20 2019
On Wednesday, 20 March 2019 at 22:11:00 UTC, Mike Franklin wrote:On Wednesday, 20 March 2019 at 21:58:46 UTC, sighoya wrote:So I can become a reviewer only, but how can I propose changes to be merged into the PR proposer's branch, do I need to clone his branch and to create a pull request in hope he accept my changes?How can I help if I'm not the one creating the PR?It needs someone willing to adopt the PR and work with reviewers to get it across the finish line. If you've never worked on DMD before, cloning the DMD, druntime, Phobos, etc. and learning how to build the compiler and run the test suite locally is the first step. Mike
Mar 21 2019
On Thursday, 21 March 2019 at 07:08:41 UTC, sighoya wrote:So I can become a reviewer only, but how can I propose changes to be merged into the PR proposer's branch, do I need to clone his branch and to create a pull request in hope he accept my changes?Create a new branch, merge the original author's work into your branch, then add your edits, and submit a new PR. That's what I'd do anyway. Mike
Mar 21 2019
On Thursday, 21 March 2019 at 11:17:52 UTC, Mike Franklin wrote:Create a new branch, merge the original author's work into your branch, then add your edits, and submit a new PR. That's what I'd do anyway. MikeGlad to hear. But does it make sense when there is already one pull request open: https://github.com/dlang/dmd/pull/8378 ?
Mar 21 2019
On Thursday, 21 March 2019 at 11:29:54 UTC, sighoya wrote:On Thursday, 21 March 2019 at 11:17:52 UTC, Mike Franklin wrote:IMO, yes. MikeCreate a new branch, merge the original author's work into your branch, then add your edits, and submit a new PR. That's what I'd do anyway. MikeGlad to hear. But does it make sense when there is already one pull request open: https://github.com/dlang/dmd/pull/8378 ?
Mar 21 2019
On Wednesday, 20 March 2019 at 22:11:00 UTC, Mike Franklin wrote:On Wednesday, 20 March 2019 at 21:58:46 UTC, sighoya wrote:So I can become a reviewer only, but how can I merge additions requested by reviewers, this can only be done by the PR proposer, right?How can I help if I'm not the one creating the PR?It needs someone willing to adopt the PR and work with reviewers to get it across the finish line. If you've never worked on DMD before, cloning the DMD, druntime, Phobos, etc. and learning how to build the compiler and run the test suite locally is the first step. Mike
Mar 21 2019
On Friday, 10 October 2014 at 17:09:08 UTC, IgorStepanov wrote:I've created DIP for my pull request. DIP: http://wiki.dlang.org/DIP66 PR: https://github.com/D-Programming-Language/dmd/pull/3998 Please, comment it.What happened to this dip? Do we have an implementation or not and what is the holdup for this being added to the compiler? It's been over one year. Multiple alias this would help me a lot and I want (multiple alias) this.
Sep 27 2020
On Sunday, 27 September 2020 at 20:43:29 UTC, IGotD- wrote:On Friday, 10 October 2014 at 17:09:08 UTC, IgorStepanov wrote:It been deprecated as Walter discovered that the current alias this introduce the diamond problem. That and other sorts of bugs that it has. -AlexI've created DIP for my pull request. DIP: http://wiki.dlang.org/DIP66 PR: https://github.com/D-Programming-Language/dmd/pull/3998 Please, comment it.What happened to this dip? Do we have an implementation or not and what is the holdup for this being added to the compiler? It's been over one year. Multiple alias this would help me a lot and I want (multiple alias) this.
Sep 27 2020
On Sunday, 27 September 2020 at 21:52:15 UTC, 12345swordy wrote:It been deprecated as Walter discovered that the current alias this introduce the diamond problem. That and other sorts of bugs that it has. -AlexIt doesn't because it isn't inheritance. What you can end up with is symbol collisions but in that case you can just give an error message. You can always go to the Rust forum and first try to convince them that Rust has multiple inheritance and then that Rust is evil because it has that. Good luck.
Sep 27 2020
On Sunday, 27 September 2020 at 22:23:27 UTC, IGotD- wrote:On Sunday, 27 September 2020 at 21:52:15 UTC, 12345swordy wrote:Walter has comment on this on reddit already. It is not happening. I'm sorry to disappoint you. What do you need multi alias this for anyway? Composite programming can already do what alias this can do expect implicit conversion. -AlexIt been deprecated as Walter discovered that the current alias this introduce the diamond problem. That and other sorts of bugs that it has. -AlexIt doesn't because it isn't inheritance.
Sep 27 2020
On Sunday, 27 September 2020 at 23:34:31 UTC, 12345swordy wrote:What do you need multi alias this for anyway? Composite programming can already do what alias this can do expect implicit conversion. -AlexYes, exactly that, creating multiple composites. I know that you can do it with mixin templates but kind of ugly. So if I have an implementation, I need a struct with that implementation in it's pure form and also structs where the implementation is inserted. Now you have a disconnected implementation and then a base struct to begin with. So if you want to reuse your code you basically have to make mixin templates of everything. Was it that solution you were referring to?
Sep 27 2020
On Sunday, 27 September 2020 at 23:53:17 UTC, IGotD- wrote:On Sunday, 27 September 2020 at 23:34:31 UTC, 12345swordy wrote:That is the solution that Walter has suggest to us. What issue that you take with this solution? Increase compile times? -AlexWhat do you need multi alias this for anyway? Composite programming can already do what alias this can do expect implicit conversion. -AlexYes, exactly that, creating multiple composites. I know that you can do it with mixin templates but kind of ugly. So if I have an implementation, I need a struct with that implementation in it's pure form and also structs where the implementation is inserted. Now you have a disconnected implementation and then a base struct to begin with. So if you want to reuse your code you basically have to make mixin templates of everything. Was it that solution you were referring to?
Sep 27 2020
On Sunday, 27 September 2020 at 21:52:15 UTC, 12345swordy wrote:It been deprecated as Walter discovered that the current alias this introduce the diamond problem. That and other sorts of bugs that it has. -AlexCouldn't this be fixed by not having inheritance of alias this?
Sep 27 2020
On Sunday, 27 September 2020 at 21:52:15 UTC, 12345swordy wrote:It been deprecated as Walter discovered that the current alias this introduce the diamond problem. That and other sorts of bugs that it has. -AlexI must criticize the cop out that many language designers claim about the diamond problem. The diamond problem is mainly an academic problem which doesn't happen much in real life. I have programmed C++ for decades and I have only encountered the diamond problem once in my lifetime and this because I was hacking around, changed the solution shortly after so that it could do without "public virtual". You can come very far with multiple inheritance without the diamond pattern. Are you saying that the detection of the diamond inheritance pattern is hard to implement, I would say that it isn't. If it detects, just emit a compiler error telling the user that such pattern isn't allowed. The diamond problem is like a fantasy monster under the bed of the language designers.
Sep 28 2020
On Monday, 28 September 2020 at 15:01:45 UTC, IGotD- wrote:On Sunday, 27 September 2020 at 21:52:15 UTC, 12345swordy wrote:Then by all means created a new thread on this and argue your case, as I am not convinced that you think it is easy to implement the diamond inheritance detection. -Alex[...]I must criticize the cop out that many language designers claim about the diamond problem. The diamond problem is mainly an academic problem which doesn't happen much in real life. I have programmed C++ for decades and I have only encountered the diamond problem once in my lifetime and this because I was hacking around, changed the solution shortly after so that it could do without "public virtual". You can come very far with multiple inheritance without the diamond pattern. Are you saying that the detection of the diamond inheritance pattern is hard to implement, I would say that it isn't. If it detects, just emit a compiler error telling the user that such pattern isn't allowed. The diamond problem is like a fantasy monster under the bed of the language designers.
Sep 28 2020
On Monday, 28 September 2020 at 17:16:31 UTC, 12345swordy wrote:Then by all means created a new thread on this and argue your case, as I am not convinced that you think it is easy to implement the diamond inheritance detection. -AlexFirst limit multiple alias this to only be valid for basic types and structs (classes are disqualified for example). Then create a list of all the types that one alias this type has also searching that type for alias this types and up in the alias this hierarchy. If one or more of the same type is found in several alias this type lists, then abort compilation. Maybe there are more efficient ways to do this but you get the idea. Am I missing something?
Sep 28 2020
On Monday, 28 September 2020 at 15:01:45 UTC, IGotD- wrote:On Sunday, 27 September 2020 at 21:52:15 UTC, 12345swordy wrote: I must criticize the cop out that many language designers claim about the diamond problem. The diamond problem is mainly an academic problem which doesn't happen much in real life. I have programmed C++ for decades and I have only encountered the diamond problem once in my lifetime and this because I was hacking around, changed the solution shortly after so that it could do without "public virtual". You can come very far with multiple inheritance without the diamond pattern. Are you saying that the detection of the diamond inheritance pattern is hard to implement, I would say that it isn't. If it detects, just emit a compiler error telling the user that such pattern isn't allowed. The diamond problem is like a fantasy monster under the bed of the language designers.I think this deserved to be better known: The diamond problem is a *solved* problem by Eiffel language, which won the 2006 ACM Software System Award: https://en.wikipedia.org/wiki/ACM_Software_System_Award And I showed the concrete example here: https://forum.dlang.org/thread/obqthozmxwzhvrafothw forum.dlang.org
Sep 28 2020
On Mon, Sep 28, 2020 at 05:59:19PM +0000, mw via Digitalmars-d wrote:I think this deserved to be better known: The diamond problem is a *solved* problem by Eiffel language, which won the 2006 ACM Software System Award: https://en.wikipedia.org/wiki/ACM_Software_System_AwardThat award has nothing to do with the diamond problem. There is nothing in the link that even mentions the diamond problem.And I showed the concrete example here: https://forum.dlang.org/thread/obqthozmxwzhvrafothw forum.dlang.orgAs somebody already said, that's all well and good for Eiffel. It's not so clear how to integrate this nicely in D. T -- Старый друг лучше новых двух.
Sep 28 2020
On Monday, 28 September 2020 at 18:13:15 UTC, H. S. Teoh wrote:On Mon, Sep 28, 2020 at 05:59:19PM +0000, mw via Digitalmars-d wrote: As somebody already said, that's all well and good for Eiffel. It's not so clear how to integrate this nicely in D.D has `alias` already, which can be used as Eiffel's `rename`, and by introducing the other same keywords (mechanism), we can adopt the Eiffel multiple inheritance. D and Eiffel are close: D picked design-by-contract from Eiffel, but throw away multiple inheritance, ... and instead introduced sub-typing, mixin, which Walter said: https://forum.dlang.org/post/rb4seo$bfm$1 digitalmars.com """ The trouble was, it was inserted without realizing it was multiple inheritance, meaning its behaviors are ad-hoc and don't make a whole lot of sense when examined carefully. """ If we really want to fix it, can do it in D3.
Sep 28 2020
On Mon, Sep 28, 2020 at 06:28:05PM +0000, mw via Digitalmars-d wrote:On Monday, 28 September 2020 at 18:13:15 UTC, H. S. Teoh wrote:[...] `alias this` is one of the things that seemed like a good idea at the time, but is turning out to be something that leads to code smells. If anything, we'd like to get rid of it rather than extend it! T -- People say I'm indecisive, but I'm not sure about that. -- YHL, CONLANGOn Mon, Sep 28, 2020 at 05:59:19PM +0000, mw via Digitalmars-d wrote: As somebody already said, that's all well and good for Eiffel. It's not so clear how to integrate this nicely in D.D has `alias` already,
Sep 28 2020
On Monday, 28 September 2020 at 18:44:51 UTC, H. S. Teoh wrote:On Mon, Sep 28, 2020 at 06:28:05PM +0000, mw via Digitalmars-d wrote:On a second thought, I agree we'd better not to extend `alias`. It's all about resolve name clashing: `alias` means synonyms; let's just borrow from Eiffel, instead of re-invent the wheels: the main concepts to solve multiple inheritance are these 5 keywords: https://www.eiffel.org/doc/eiffel/Eiffel_programming_language_reserved_words `rename` `export` `undefine` `redefine` -- D's override `select`On Monday, 28 September 2020 at 18:13:15 UTC, H. S. Teoh wrote:[...] `alias this` is one of the things that seemed like a good idea at the time, but is turning out to be something that leads to code smells. If anything, we'd like to get rid of it rather than extend it!On Mon, Sep 28, 2020 at 05:59:19PM +0000, mw via Digitalmars-d wrote: As somebody already said, that's all well and good for Eiffel. It's not so clear how to integrate this nicely in D.D has `alias` already,
Sep 28 2020
On Mon, Sep 28, 2020 at 06:56:40PM +0000, mw via Digitalmars-d wrote: [...]It's all about resolve name clashing: `alias` means synonyms; let's just borrow from Eiffel, instead of re-invent the wheels: the main concepts to solve multiple inheritance are these 5 keywords: https://www.eiffel.org/doc/eiffel/Eiffel_programming_language_reserved_words `rename` `export` `undefine` `redefine` -- D's override `select`I don't know Eiffel; could you enlighten me as to how it solves the following instance of the diamond problem? struct Resource { this(...) { acquireResource(); } ~this() { releaseResource(); } } class A { Resource x; } class B : A { ... } class C : A { ... } class D : B, C { // Should D have one instance of A.x, or two instances // of A.x? (Putting aside the question of naming for the // time being -- let's pretend we have a way of // addressing x somehow in either case.) } I can see some situations for which you want two distinct instances of A.x (there should be two distinct resources acquired by D), and some other situations for which you want them to be the same (the same resource should be shared by B and C). How does Eiffel cater to both cases? Regardless of how Eiffel does it, supporting either case in D is going to be a mess, because it changes the memory layout of B and C, meaning you'd have to decide beforehand which solution is desired, even if D hasn't even been written yet (and the need to implement D hasn't even come up yet). The only way I can think of to support both cases without requiring foretelling the future is to access A's members via a virtual table, which will basically break a lot of the ABI, introduce another layer of indirection (with its performance implications), and require extensive rewriting of D's codegen, etc.. Basically, a HUGE amount of work to implement it and fix the resulting breakage, all for the marginal (I'd even say questionable) benefit of being able to use multiple inheritance. I honestly doubt this will ever happen in D, even if you set aside the question of whether this is even a good idea to begin with. T -- For every argument for something, there is always an equal and opposite argument against it. Debates don't give answers, only wounded or inflated egos.
Sep 28 2020
On Monday, 28 September 2020 at 19:41:07 UTC, H. S. Teoh wrote:On Mon, Sep 28, 2020 at 06:56:40PM +0000, mw via Digitalmars-d wrote: [...]The Resource A.x in your example is what I have shown in my example PERSON.addr and PERSON.name here: https://forum.dlang.org/thread/obqthozmxwzhvrafothw forum.dlang.org 1) In Eiffel, by default the attribute is shared/joined, meaning in your above code as it its, there is only 1 `x` in D; and that's the PERSON.name in my example (no special treatment, it's just joined in D). 2) If the application do want separate instances of one attribute, PERSON.addr in my example, then use `rename` / `select` to choose the one the programmer wanted semantics in mind. So in this case, your example is: class B : A {...} class C : A {...} // let's suppose the application's semantics want to use C.x, but still keep B.x class D1 : B(rename x as bx) // (rename ...) is my invented Eiffel syntax in D , C(select x) { // (select ...) is my invented Eiffel syntax in D ... } // let's suppose the application's semantics want to use B.x, but still keep C.x class D2 : B(select x) , C(rename x as cx) { ... } // let's suppose the application's semantics want to use B.x, but remove C.x class D3 : B(select x) , C(undefine x) { ... } // let's suppose the application's semantics want to use C.x, but remove B.x class D4 : B(undefine x) , C(select x) { ... } // let's suppose the application's semantics want to remove both B.x and C.x class D5 : B(undefine x) , C(undefine x) { redefine x; // need to redefine x } // let's suppose the application's semantics want to remove keep B.x and C.x class D6 : B(rename x as bx) , C(rename x as cx) { redefine x; // need to redefine x } ... as you can see, all different application semantics can be specified by the programmer. Please check my previous PERSON.addr example more carefully. PERSON.addr UK_RESIDENT(: PERSON).addr US_RESIDENT(: PERSON).addr VISITOR(: UK_RESIDENT, US_RESIDENT).addr https://forum.dlang.org/post/obqthozmxwzhvrafothw forum.dlang.orgIt's all about resolve name clashing: `alias` means synonyms; let's just borrow from Eiffel, instead of re-invent the wheels: the main concepts to solve multiple inheritance are these 5 keywords: https://www.eiffel.org/doc/eiffel/Eiffel_programming_language_reserved_words `rename` `export` `undefine` `redefine` -- D's override `select`I don't know Eiffel; could you enlighten me as to how it solves the following instance of the diamond problem? struct Resource { this(...) { acquireResource(); } ~this() { releaseResource(); } } class A { Resource x; } class B : A { ... } class C : A { ... } class D : B, C { // Should D have one instance of A.x, or two instances // of A.x? (Putting aside the question of naming for the // time being -- let's pretend we have a way of // addressing x somehow in either case.) } I can see some situations for which you want two distinct instances of A.x (there should be two distinct resources acquired by D), and some other situations for which you want them to be the same (the same resource should be shared by B and C). How does Eiffel cater to both cases?
Sep 28 2020
On Monday, 28 September 2020 at 20:28:17 UTC, mw wrote:On Monday, 28 September 2020 at 19:41:07 UTC, H. S. Teoh wrote:I didn't handle just 2 cases, but all kinds of cases, whether in the Derived class D.x. you want *any* or even *none* of A.x, B.x, C.x, all kinds of combination, the programmer can specify exactly what s/he wanted using -- undefine -- redefine -- rename -- select I showed 5 examples in Eiffel way, you can do it as an exercise of all the other combinations.I can see some situations for which you want two distinct instances of A.x (there should be two distinct resources acquired by D), and some other situations for which you want them to be the same (the same resource should be shared by B and C). How does Eiffel cater to both cases?
Sep 28 2020
On Mon, Sep 28, 2020 at 08:45:33PM +0000, mw via Digitalmars-d wrote:On Monday, 28 September 2020 at 20:28:17 UTC, mw wrote:Good. Now make it work for D. :-P Note that this is easy to do in Eiffel because it has a dynamic memory layout; D does not. Making it work for D will be extremely complex, and probably will not justify the comparatively meager benefits relative to the cost. T -- Today's society is one of specialization: as you grow, you learn more and more about less and less. Eventually, you know everything about nothing.On Monday, 28 September 2020 at 19:41:07 UTC, H. S. Teoh wrote:I didn't handle just 2 cases, but all kinds of cases, whether in the Derived class D.x. you want *any* or even *none* of A.x, B.x, C.x, all kinds of combination, the programmer can specify exactly what s/he wanted using -- undefine -- redefine -- rename -- select I showed 5 examples in Eiffel way, you can do it as an exercise of all the other combinations.I can see some situations for which you want two distinct instances of A.x (there should be two distinct resources acquired by D), and some other situations for which you want them to be the same (the same resource should be shared by B and C). How does Eiffel cater to both cases?
Sep 28 2020
On Monday, 28 September 2020 at 21:11:04 UTC, H. S. Teoh wrote:Good. Now make it work for D. :-P Note that this is easy to do in Eiffel because it has a dynamic memory layout; D does not. Making it work for D will beNot sure what you mean by dynamic memory layout. Eiffel is a statically compiled language. All the class's memory layout is know at compile time (as it's fully specified by the programmer in the source code). BTW, many (if not all) Eiffel compilers actually compile Eiffel program to C (as target language). I just uploaded SmartEiffel (open source) 1.1 compiler, and my previous visitor example to: https://github.com/mingwugmail/dlang_tour/tree/master/eiffel You can play with it. And the generated C code of my example is: https://github.com/mingwugmail/dlang_tour/blob/master/eiffel/visitor/app1.c You can study it.extremely complex, and probably will not justify the comparatively meager benefits relative to the cost.Well, we are solving the sub-typing `alias this` & various mixin problems here in Dlang in the very thread.
Sep 28 2020
On Monday, 28 September 2020 at 18:44:51 UTC, H. S. Teoh wrote:[...] `alias this` is one of the things that seemed like a good idea at the time, but is turning out to be something that leads to code smells. If anything, we'd like to get rid of it rather than extend it! TSo what is the alternative? I'm not that enthusiastic of mixin templates because it just inserts everything like you would copy and paste text. That way you have to be careful when using several mixin templates that they don't use the exact same variable name for example so it kind of becomes inconvenient. What happens with private: and public:, do they bleed over into the non mixin code? I like alias this because it still offers a way to encapsulation what you want to insert. Multiple inheritance isn't that much of a problem as interfaces solves that but still you want to be able to reuse implementations and not create wrappers for inner structs/classes by hand in every instance you use it.
Sep 28 2020
On 9/28/20 2:44 PM, H. S. Teoh wrote:On Mon, Sep 28, 2020 at 06:28:05PM +0000, mw via Digitalmars-d wrote:I'd love to get a better idea about this, e.g. a few clear examples of bad uses and other few good examples where it's a win. My intuition vaguely revolves around "aliasing to an rvalue is bad and lvalue is good" but I year for clarity.On Monday, 28 September 2020 at 18:13:15 UTC, H. S. Teoh wrote:[...] `alias this` is one of the things that seemed like a good idea at the time, but is turning out to be something that leads to code smells. If anything, we'd like to get rid of it rather than extend it!On Mon, Sep 28, 2020 at 05:59:19PM +0000, mw via Digitalmars-d wrote: As somebody already said, that's all well and good for Eiffel. It's not so clear how to integrate this nicely in D.D has `alias` already,
Sep 28 2020
On 9/28/20 3:55 PM, Andrei Alexandrescu wrote:On 9/28/20 2:44 PM, H. S. Teoh wrote:s/year/yearn/On Mon, Sep 28, 2020 at 06:28:05PM +0000, mw via Digitalmars-d wrote:I'd love to get a better idea about this, e.g. a few clear examples of bad uses and other few good examples where it's a win. My intuition vaguely revolves around "aliasing to an rvalue is bad and lvalue is good" but I year for clarity.On Monday, 28 September 2020 at 18:13:15 UTC, H. S. Teoh wrote:[...] `alias this` is one of the things that seemed like a good idea at the time, but is turning out to be something that leads to code smells. If anything, we'd like to get rid of it rather than extend it!On Mon, Sep 28, 2020 at 05:59:19PM +0000, mw via Digitalmars-d wrote: As somebody already said, that's all well and good for Eiffel. It's not so clear how to integrate this nicely in D.D has `alias` already,
Sep 28 2020
On Monday, 28 September 2020 at 19:55:10 UTC, Andrei Alexandrescu wrote:On 9/28/20 2:44 PM, H. S. Teoh wrote:An example of bad use is when you "alias this" a class inside a class. A good case is when you "alias this" a struct inside a struct. An ideal case for me is allowing classes to implement opimplicit that strictly returns a copy of a value type, so that we can get rid alias this for classes. -AlexOn Mon, Sep 28, 2020 at 06:28:05PM +0000, mw via Digitalmars-d wrote:I'd love to get a better idea about this, e.g. a few clear examples of bad uses and other few good examples where it's a win. My intuition vaguely revolves around "aliasing to an rvalue is bad and lvalue is good" but I year for clarity.On Monday, 28 September 2020 at 18:13:15 UTC, H. S. Teoh wrote:[...] `alias this` is one of the things that seemed like a good idea at the time, but is turning out to be something that leads to code smells. If anything, we'd like to get rid of it rather than extend it!On Mon, Sep 28, 2020 at 05:59:19PM +0000, mw via Digitalmars-d wrote: As somebody already said, that's all well and good for Eiffel. It's not so clear how to integrate this nicely in D.D has `alias` already,
Sep 28 2020
On 9/28/2020 12:55 PM, Andrei Alexandrescu wrote:I'd love to get a better idea about this, e.g. a few clear examples of bad uses and other few good examples where it's a win. My intuition vaguely revolves around "aliasing to an rvalue is bad and lvalue is good" but I year for clarity.There are several bugzilla issues on alias this that aren't fixed because there was no clear way to do it that both made sense and did not break existing code. If a class hierarchy has alias this, when does the compiler go looking down the alias this, and when does it go looking at the base class and interfaces? (Of course the base class can have an alias this, and an alias this can have a base class.) You have essentially *two* multiple inheritance systems in play at the same time, each obeying different rules. Couple that with the current arbitrary random rules about how alias this behaves for classes, and any coherent MI alias this scheme would randomly break existing code.
Sep 28 2020
On Tuesday, 29 September 2020 at 03:53:02 UTC, Walter Bright wrote:On 9/28/2020 12:55 PM, Andrei Alexandrescu wrote:You could take Manu Evans advice and allow structs to inherent from other structs traditionally like in c++ and deprecate alias this. That would solve 80 percent of the problem. - Alex[...]There are several bugzilla issues on alias this that aren't fixed because there was no clear way to do it that both made sense and did not break existing code. If a class hierarchy has alias this, when does the compiler go looking down the alias this, and when does it go looking at the base class and interfaces? (Of course the base class can have an alias this, and an alias this can have a base class.) You have essentially *two* multiple inheritance systems in play at the same time, each obeying different rules. Couple that with the current arbitrary random rules about how alias this behaves for classes, and any coherent MI alias this scheme would randomly break existing code.
Sep 29 2020
On Tuesday, 29 September 2020 at 13:17:50 UTC, 12345swordy wrote:You could take Manu Evans advice and allow structs to inherent from other structs traditionally like in c++ and deprecate alias this. That would solve 80 percent of the problem. - AlexI did a grep for `alias this` in Phobos last time this topic came up. By my count, use of `alias this` was split almost exactly 50/50 between forwarding to a member variable and forwarding to the result of a method.
Sep 29 2020
On 9/29/20 9:13 PM, Paul Backus wrote:On Tuesday, 29 September 2020 at 13:17:50 UTC, 12345swordy wrote:How frequently did the method return ref vs rvalue?You could take Manu Evans advice and allow structs to inherent from other structs traditionally like in c++ and deprecate alias this. That would solve 80 percent of the problem. - AlexI did a grep for `alias this` in Phobos last time this topic came up. By my count, use of `alias this` was split almost exactly 50/50 between forwarding to a member variable and forwarding to the result of a method.
Sep 29 2020
On Monday, 28 September 2020 at 19:55:10 UTC, Andrei Alexandrescu wrote:I'd love to get a better idea about this, e.g. a few clear examples of bad uses and other few good examples where it's a win. My intuition vaguely revolves around "aliasing to an rvalue is bad and lvalue is good" but I year for clarity.What's good about `alias this` ------------------------------ `alias this` is used for 2 primary purposes: 1. Forwarding a member's interface to its containing object's interface 2. Implicit casting and subtyping which are fundamentally different but with similar use cases ``` struct A { int x; } struct B { A a; alias a this; int y; } void PassA(A a) {} void main() { B b; int i = b.x; // A.x was forwarded through B int j = b.y; PassA(b); // B was implicitly cast to A } ``` `alias this` is actually useless for classes, because the same thing can be achieved with inheritance: ``` class A { int x; } class B : A { int y; } void PassA(A a) {} void main() { auto b = new B(); int i = b.x; // A.x was forwarded through B int j = b.y; PassA(b); // B was implicitly cast to A } ``` What's bad about `alias this` ----------------------------- Walter addressed the problem with `alias this` here:If a class hierarchy has alias this, when does the compiler go looking down the alias this, and when does it go looking at the base class and interfaces? (Of course the base class can have an alias this, and an alias this can have a base class.) You have essentially *two* multiple inheritance systems in play at the same time, each obeying different rules.Couple that with the current arbitrary random rules about how alias this behaves for classes, and any coherent MI alias this scheme would randomly break existing code.In other words, its too complex, and adding multiple `alias this` would only compound that complexity. My 2 cents ---------- `alias this` is useless for classes unless users want to abuse it to create "dual" inheritance by both inheriting from another class, and `alias this` a member simultaneously. Just use inheritance. If you need multiple inheritance, inherit from multiple interfaces and use D's excellent metaprogramming facilities to auto-implement each interface, or auto-forward members that implement the interfaces. ``` interface A { property int x(); } mixin template Aimp() { property int x() { return 0; } } interface B { property int y(); } mixin template Bimp() { property int y() { return 0; } } class C : A, B { mixin Aimp; mixin Bimp; } void PassA(A a) {} void PassB(B b) {} void main() { auto c = new C(); int i = c.x; // A's implementation in C int j = c.y; // B's implementation in C PassA(c); // C implicitly cast to A PassB(c); // C implicitly cast to B } ``` Where `alias this` has no alternative for structs because structs cannot inherit and cannot implement interfaces. D has sufficient metaprogramming facilities to auto-forward members, but the missing piece is implicit casting. ``` mixin template Aimp() { int x; } mixin template Bimp() { int y; } struct C { mixin Aimp; mixin Bimp; } void PassA(A a) {} // Error: What do we put here when we want a type that implements `A`. There is no such type? void PassB(B b) {} // Error: What do we put here when we want a type that implements `B`, There is no such type? void main() { auto c = new C(); int i = c.x; // A's implementation in C int j = c.y; // B's implementation in C PassA(c); // Error: C cannot implicitly cast to A PassB(c); // Error: C canot implicitly cast to B } ``` So, here are a couple of proposals off the top of my head. I imagine someone more talented than I can think of a few more: 1. Deprecate `alias this` for classes, and implement multiple `alias this` for structs. That will give users the composition feature they need, and in addition, because structs cannot inherit, it removes the complexity Walter spoke of. 2. Add `opImplicit`, implicit copy constructors, or something of that ilk. Then users only need to forward members using D's metaprogramming facilities. Both uses of `alias this` are covered, but no `alias this` is required. `alias this` can then be deprecated entirely. 3. Add struct inheritance like C++.
Sep 29 2020
On Wednesday, 30 September 2020 at 01:36:59 UTC, Mike wrote:So, here are a couple of proposals off the top of my head. I imagine someone more talented than I can think of a few more: 1. Deprecate `alias this` for classes, and implement multiple `alias this` for structs. That will give users the composition feature they need, and in addition, because structs cannot inherit, it removes the complexity Walter spoke of. 2. Add `opImplicit`, implicit copy constructors, or something of that ilk. Then users only need to forward members using D's metaprogramming facilities. Both uses of `alias this` are covered, but no `alias this` is required. `alias this` can then be deprecated entirely. 3. Add struct inheritance like C++.4. Somehow allow structs to implement interfaces.
Sep 29 2020
On 9/29/20 9:42 PM, Mike wrote:On Wednesday, 30 September 2020 at 01:36:59 UTC, Mike wrote:I'd love it if interfaces could implement methods. (All MI related issues are related to state, not implementation of methods.)So, here are a couple of proposals off the top of my head. I imagine someone more talented than I can think of a few more: 1. Deprecate `alias this` for classes, and implement multiple `alias this` for structs. That will give users the composition feature they need, and in addition, because structs cannot inherit, it removes the complexity Walter spoke of. 2. Add `opImplicit`, implicit copy constructors, or something of that ilk. Then users only need to forward members using D's metaprogramming facilities. Both uses of `alias this` are covered, but no `alias this` is required. `alias this` can then be deprecated entirely. 3. Add struct inheritance like C++.4. Somehow allow structs to implement interfaces.
Sep 29 2020
On 9/29/20 10:08 PM, Andrei Alexandrescu wrote:On 9/29/20 9:42 PM, Mike wrote:BTW forgot to mention - this is from the category of removing limitations.On Wednesday, 30 September 2020 at 01:36:59 UTC, Mike wrote:I'd love it if interfaces could implement methods. (All MI related issues are related to state, not implementation of methods.)So, here are a couple of proposals off the top of my head. I imagine someone more talented than I can think of a few more: 1. Deprecate `alias this` for classes, and implement multiple `alias this` for structs. That will give users the composition feature they need, and in addition, because structs cannot inherit, it removes the complexity Walter spoke of. 2. Add `opImplicit`, implicit copy constructors, or something of that ilk. Then users only need to forward members using D's metaprogramming facilities. Both uses of `alias this` are covered, but no `alias this` is required. `alias this` can then be deprecated entirely. 3. Add struct inheritance like C++.4. Somehow allow structs to implement interfaces.
Sep 29 2020
On Wednesday, 30 September 2020 at 02:08:17 UTC, Andrei Alexandrescu wrote:On 9/29/20 9:42 PM, Mike wrote:Interface Members": https://devblogs.microsoft.com/dotnet/default-implementations-in-interfaces/ However, the didn't finish the implementation and deferred this very important component: https://github.com/dotnet/csharplang/issues/2337 I've used this That being said, I think that is somewhat tangential to the topic of this thread which I argue can be boiled down to "multiple alias this (or some other feature) is needed to do composition well with structs".On Wednesday, 30 September 2020 at 01:36:59 UTC, Mike wrote:I'd love it if interfaces could implement methods. (All MI related issues are related to state, not implementation of methods.)So, here are a couple of proposals off the top of my head. I imagine someone more talented than I can think of a few more: 1. Deprecate `alias this` for classes, and implement multiple `alias this` for structs. That will give users the composition feature they need, and in addition, because structs cannot inherit, it removes the complexity Walter spoke of. 2. Add `opImplicit`, implicit copy constructors, or something of that ilk. Then users only need to forward members using D's metaprogramming facilities. Both uses of `alias this` are covered, but no `alias this` is required. `alias this` can then be deprecated entirely. 3. Add struct inheritance like C++.4. Somehow allow structs to implement interfaces.
Sep 29 2020
On Wed, Sep 30, 2020 at 02:34:27AM +0000, Mike via Digitalmars-d wrote:On Wednesday, 30 September 2020 at 02:08:17 UTC, Andrei Alexandrescu wrote:[...]Don't we already have this in D? interface I { void method1(); // overridable method final void method2() {} // default method } class C : I { void method1() {} } Of course, currently method bodies in interfaces are only allowed when T -- My program has no bugs! Only undocumented features...I'd love it if interfaces could implement methods. (All MI related issues are related to state, not implementation of methods.)Interface Members": https://devblogs.microsoft.com/dotnet/default-implementations-in-interfaces/ However, the didn't finish the implementation and deferred this very important component: https://github.com/dotnet/csharplang/issues/2337 I've used this feature quite a bit, but it's only mildly useful until
Sep 29 2020
On 9/30/20 12:12 AM, H. S. Teoh wrote:On Wed, Sep 30, 2020 at 02:34:27AM +0000, Mike via Digitalmars-d wrote:It looks like default method bodies are virtual and can be overridden. I sort of remember at least having discussions about doing something like this, but I don't think it ever happened. -SteveOn Wednesday, 30 September 2020 at 02:08:17 UTC, Andrei Alexandrescu wrote:[...]Don't we already have this in D? interface I { void method1(); // overridable method final void method2() {} // default method } class C : I { void method1() {} } Of course, currently method bodies in interfaces are only allowed whenI'd love it if interfaces could implement methods. (All MI related issues are related to state, not implementation of methods.)Interface Members": https://devblogs.microsoft.com/dotnet/default-implementations-in-interfaces/ However, the didn't finish the implementation and deferred this very important component: https://github.com/dotnet/csharplang/issues/2337 I've used this feature quite a bit, but it's only mildly useful until
Sep 29 2020
On Wed, Sep 30, 2020 at 12:48:56AM -0400, Steven Schveighoffer via Digitalmars-d wrote:On 9/30/20 12:12 AM, H. S. Teoh wrote:[...]On Wednesday, 30 September 2020 at 02:08:17 UTC, Andrei Alexandrescu wrote:[...]I'd love it if interfaces could implement methods. (All MI related issues are related to state, not implementation of methods.)[...] If we allow virtual non-abstract methods in interfaces, that would certainly be MI. Though I'm guessing some people won't be happy until interfaces also carry state... :-P T -- You are only young once, but you can stay immature indefinitely. -- azephrahelDon't we already have this in D? interface I { void method1(); // overridable method final void method2() {} // default method } class C : I { void method1() {} } Of course, currently method bodies in interfaces are only allowedIt looks like default method bodies are virtual and can be overridden. I sort of remember at least having discussions about doing something like this, but I don't think it ever happened.
Sep 29 2020
On 30/09/2020 2:42 PM, Mike wrote:4. Somehow allow structs to implement interfaces.Alternatively signatures. A static interface that inherits from an implementation type like struct or class. https://gist.github.com/rikkimax/826e1c4deb531e8dd993815bf914acea#signatures
Sep 29 2020
On Wednesday, 30 September 2020 at 01:42:30 UTC, Mike wrote:4. Somehow allow structs to implement interfaces.Wouldn't that mean a vtable and therefore a POD violation?
Sep 30 2020
On Wednesday, 30 September 2020 at 01:36:59 UTC, Mike wrote:On Monday, 28 September 2020 at 19:55:10 UTC, Andrei Alexandrescu wrote: 1. Deprecate `alias this` for classes, and implement multiple `alias this` for structs. That will give users the composition feature they need, and in addition, because structs cannot inherit, it removes the complexity Walter spoke of.This! We've never used alias this for classes, I'm wondering if there's something like that in Phobos, or in other projects ...
Sep 30 2020
On Wednesday, 30 September 2020 at 07:54:39 UTC, Paolo Invernizzi wrote:On Wednesday, 30 September 2020 at 01:36:59 UTC, Mike wrote:There's quite a few tests in Phobos for alias this on classes, but I wasn't able to find a single feature that uses this (and frankly, I'd be surprised if I did). -- SimenOn Monday, 28 September 2020 at 19:55:10 UTC, Andrei Alexandrescu wrote: 1. Deprecate `alias this` for classes, and implement multiple `alias this` for structs. That will give users the composition feature they need, and in addition, because structs cannot inherit, it removes the complexity Walter spoke of.This! We've never used alias this for classes, I'm wondering if there's something like that in Phobos, or in other projects ...
Sep 30 2020
On Wed, Sep 30, 2020 at 07:54:39AM +0000, Paolo Invernizzi via Digitalmars-d wrote:On Wednesday, 30 September 2020 at 01:36:59 UTC, Mike wrote:[...] I haven't used alias on classes either, but I did frequently use alias this on structs that wrap classes. Which may lead to some of the same complexity: struct S implicitly converts to class C which may in turn implicitly convert to base class B or interface I. But probably not as horrible as using alias this inside a class. T -- Three out of two people have difficulties with fractions. -- Dirk EddelbuettelOn Monday, 28 September 2020 at 19:55:10 UTC, Andrei Alexandrescu wrote: 1. Deprecate `alias this` for classes, and implement multiple `alias this` for structs. That will give users the composition feature they need, and in addition, because structs cannot inherit, it removes the complexity Walter spoke of.This! We've never used alias this for classes, I'm wondering if there's something like that in Phobos, or in other projects ...
Sep 30 2020
On Wednesday, 30 September 2020 at 12:34:03 UTC, H. S. Teoh wrote:On Wed, Sep 30, 2020 at 07:54:39AM +0000, Paolo Invernizzi via Digitalmars-d wrote:Indeed, I imagine that's a much simpler case to handle in the compiler. It would be interesting to have a PR that disable alias this for classes just to have a look on how many external dub projects are impacted by that ...On Wednesday, 30 September 2020 at 01:36:59 UTC, Mike wrote:[...] I haven't used alias on classes either, but I did frequently use alias this on structs that wrap classes. Which may lead to some of the same complexity: struct S implicitly converts to class C which may in turn implicitly convert to base class B or interface I. But probably not as horrible as using alias this inside a class. TOn Monday, 28 September 2020 at 19:55:10 UTC, Andrei Alexandrescu wrote: 1. Deprecate `alias this` for classes, and implement multiple `alias this` for structs. That will give users the composition feature they need, and in addition, because structs cannot inherit, it removes the complexity Walter spoke of.This! We've never used alias this for classes, I'm wondering if there's something like that in Phobos, or in other projects ...
Sep 30 2020
On Wednesday, 30 September 2020 at 12:40:03 UTC, Paolo Invernizzi wrote:On Wednesday, 30 September 2020 at 12:34:03 UTC, H. S. Teoh wrote:On Wed, Sep 30, 2020 at 07:54:39AM +0000, Paolo Invernizzi via Digitalmars-d wrote:On Wednesday, 30 September 2020 at 01:36:59 UTC, Mike wrote:On Monday, 28 September 2020 at 19:55:10 UTC, Andrei Alexandrescu wrote: 1. Deprecate `alias this` for classes, and implement multiple `alias this` for structs. That will give users the composition feature they need, and in addition, because structs cannot inherit, it removes the complexity Walter spoke of.This! We've never used alias this for classes, I'm wondering if there's something like that in Phobos, or in other projects ...It would be interesting to have a PR that disable alias this for classes just to have a look on how many external dub projects are impacted by that ...Right, we just had a discussion last month on the problems I found here: https://forum.dlang.org/post/pjxwebeyiypgtgxqmcdp forum.dlang.org class SharedArray(T) { public T[] array; alias array this; // subtyping } The point is, these D language features are not well-thought and designed, and when people start to use it and mix with other language features, all kinds of weird corner-case behavior show up and surprise the user.
Sep 30 2020
On Wednesday, 30 September 2020 at 12:40:03 UTC, Paolo Invernizzi wrote:Indeed, I imagine that's a much simpler case to handle in the compiler. It would be interesting to have a PR that disable alias this for classes just to have a look on how many external dub projects are impacted by that ...https://github.com/dlang/dmd/pull/11817
Sep 30 2020
On Wednesday, 30 September 2020 at 07:54:39 UTC, Paolo Invernizzi wrote:On Wednesday, 30 September 2020 at 01:36:59 UTC, Mike wrote:To be more precise, you don't actually have to deprecated alias this for classes. You could keep singular alias this for classes and then add multiple alias this for structs. That may satisfy the "add, don't change" crowd, while still giving users the struct composition features that D currently lacks.1. Deprecate `alias this` for classes, and implement multiple `alias this` for structs. That will give users the composition feature they need, and in addition, because structs cannot inherit, it removes the complexity Walter spoke of.This! We've never used alias this for classes, I'm wondering if there's something like that in Phobos, or in other projects ...
Sep 30 2020
On Thursday, 1 October 2020 at 00:40:05 UTC, Mike wrote:To be more precise, you don't actually have to deprecated alias this for classes. You could keep singular alias this for classes and then add multiple alias this for structs. That may satisfy the "add, don't change" crowd, while still giving users the struct composition features that D currently lacks.Yes, an extension for structs only seems like a good way to avoid adding edge cases. Here's a suggestion. https://forum.dlang.org/thread/uniyvmvjopeyyxmphfso forum.dlang.org
Aug 05 2021
On Wednesday, 30 September 2020 at 01:36:59 UTC, Mike wrote:1. Deprecate `alias this` for classes, and implement multiple `alias this` for structs. That will give users the composition feature they need, and in addition, because structs cannot inherit, it removes the complexity Walter spoke of. 2. Add `opImplicit`, implicit copy constructors, or something of that ilk. Then users only need to forward members using D's metaprogramming facilities. Both uses of `alias this` are covered, but no `alias this` is required. `alias this` can then be deprecated entirely. 3. Add struct inheritance like C++.4. Remove "alias this" completely, use mixin templates instead. I originally misunderstood template mixins believing it was more or less just expansion into the scope. It turns out that there is a lot more going on under the hood, which makes the template mixin work like inheritance. This currently badly documented which makes people believe that template mixins are more limited.
Sep 30 2020
On Monday, 28 September 2020 at 18:44:51 UTC, H. S. Teoh wrote:`alias this` is one of the things that seemed like a good idea at the time, but is turning out to be something that leads to code smells. If anything, we'd like to get rid of it rather than extend it! TAs it seems, the language maintainers want to remove alias this totally. If that's the case shouldn't the documentation be updated telling the programmers that if they write new code they should avoid alias this, and then also direct them to alternative solutions.
Sep 29 2020
On Tuesday, 29 September 2020 at 09:21:42 UTC, IGotD- wrote:On Monday, 28 September 2020 at 18:44:51 UTC, H. S. Teoh wrote:Further more, this in the "alias this" documentation. "Multiple AliasThis are allowed. For implicit conversions and forwarded lookups, all AliasThis declarations are attempted; if more than one AliasThis is eligible, the ambiguity is disallowed by raising an error. Note: Multiple AliasThis is currently unimplemented." which is totally out of date, needs to be removed. Further more, there seems to be some magic going on with mixin templates when it comes to constructors and deconstructors. This is not documented.`alias this` is one of the things that seemed like a good idea at the time, but is turning out to be something that leads to code smells. If anything, we'd like to get rid of it rather than extend it! TAs it seems, the language maintainers want to remove alias this totally. If that's the case shouldn't the documentation be updated telling the programmers that if they write new code they should avoid alias this, and then also direct them to alternative solutions.
Sep 29 2020
On 9/29/20 2:37 PM, IGotD- wrote:On Tuesday, 29 September 2020 at 09:21:42 UTC, IGotD- wrote:Ouch. A PR to change that would be in order regardless of future actions.On Monday, 28 September 2020 at 18:44:51 UTC, H. S. Teoh wrote:Further more, this in the "alias this" documentation. "Multiple AliasThis are allowed. For implicit conversions and forwarded lookups, all AliasThis declarations are attempted; if more than one AliasThis is eligible, the ambiguity is disallowed by raising an error. Note: Multiple AliasThis is currently unimplemented." which is totally out of date, needs to be removed.`alias this` is one of the things that seemed like a good idea at the time, but is turning out to be something that leads to code smells. If anything, we'd like to get rid of it rather than extend it! TAs it seems, the language maintainers want to remove alias this totally. If that's the case shouldn't the documentation be updated telling the programmers that if they write new code they should avoid alias this, and then also direct them to alternative solutions.
Sep 29 2020
On 9/29/20 8:46 PM, Andrei Alexandrescu wrote:On 9/29/20 2:37 PM, IGotD- wrote:Time waits for no one. https://github.com/dlang/dlang.org/pull/2862On Tuesday, 29 September 2020 at 09:21:42 UTC, IGotD- wrote:Ouch. A PR to change that would be in order regardless of future actions.On Monday, 28 September 2020 at 18:44:51 UTC, H. S. Teoh wrote:Further more, this in the "alias this" documentation. "Multiple AliasThis are allowed. For implicit conversions and forwarded lookups, all AliasThis declarations are attempted; if more than one AliasThis is eligible, the ambiguity is disallowed by raising an error. Note: Multiple AliasThis is currently unimplemented." which is totally out of date, needs to be removed.`alias this` is one of the things that seemed like a good idea at the time, but is turning out to be something that leads to code smells. If anything, we'd like to get rid of it rather than extend it! TAs it seems, the language maintainers want to remove alias this totally. If that's the case shouldn't the documentation be updated telling the programmers that if they write new code they should avoid alias this, and then also direct them to alternative solutions.
Sep 29 2020
On Monday, 28 September 2020 at 18:13:15 UTC, H. S. Teoh wrote:On Mon, Sep 28, 2020 at 05:59:19PM +0000, mw via Digitalmars-d wrote:The two hallmarks of Eiffel, is design-by-contract and multiple inheritance, which is known in academics (in my former life). it's a pity that D only picked design-by-contract from Eiffel, but throw away multiple inheritance, ... and instead introduced sub-typing, mixin, which Walter said: https://forum.dlang.org/post/rb4seo$bfm$1 digitalmars.com """ The trouble was, it was inserted without realizing it was multiple inheritance, meaning its behaviors are ad-hoc and don't make a whole lot of sense when examined carefully. """ If we really want to fix it, can do it in D3.I think this deserved to be better known: The diamond problem is a *solved* problem by Eiffel language, which won the 2006 ACM Software System Award: https://en.wikipedia.org/wiki/ACM_Software_System_AwardThat award has nothing to do with the diamond problem. There is nothing in the link that even mentions the diamond problem.
Sep 28 2020