digitalmars.D - Why can't we derive struct's?
- Manu (22/22) Dec 19 2018 I've long since become bored of this design decision. Is there good
- Basile B. (27/32) Dec 19 2018 Yes but another possible semantic for a struct inheritance list
- Manu (11/44) Dec 19 2018 I think strong traits are a different thing, otherwise you're
- Rubn (13/40) Dec 19 2018 I imagine inheritance comes with things like being able to cast a
- Walter Bright (8/13) Dec 19 2018 `alias this` can alias to a function, that doesn't work very well with t...
- Manu (13/22) Dec 20 2018 Right, by necessity, because an empty struct member takes padded space
- Steven Schveighoffer (19/30) Dec 20 2018 Yes, it does take 1 byte. I believe the reasoning was so it could have a...
- Manu (18/47) Dec 20 2018 Right, but that's still pretty shit, and I still don't know what
- H. S. Teoh (9/17) Dec 20 2018 There has been multiple attempts to implement it, but none were
- Walter Bright (10/12) Dec 20 2018 Nobody has figured out the semantics of single alias this, either (when ...
- Manu (5/19) Dec 20 2018 I don't think I've ever wanted multiple inheritance in D, but I do want
- Walter Bright (5/7) Dec 21 2018 Another feature that looks great in the small, but turns into a hopeless...
- Jonathan M Davis (36/43) Dec 27 2018 Honestly, over time, I've come to dislike implicit conversions more and
- Steven Schveighoffer (20/63) Dec 27 2018 Well, implicit conversions of builtin types is not something a mere user...
- luckoverthere (26/34) Dec 27 2018 Arguably, in a sense, we already have multiple alias this's. It
- H. S. Teoh (9/36) Dec 27 2018 [...]
- luckoverthere (15/52) Dec 27 2018 Indeed, keen observation!
- H. S. Teoh (9/17) Dec 27 2018 [...]
- 12345swordy (5/33) Dec 21 2018 I want implicit conversions here as well.What I don't want is
- Atila Neves (6/20) Dec 21 2018 I don't think any lisper has ever complained about Lisp macros -
- Walter Bright (5/9) Dec 21 2018 Probably because Lisp is unusable without macros, sort of like how C and...
- Atila Neves (20/31) Dec 21 2018 Lisp is perfectly usable without macros, it's just that it would
- Walter Bright (15/34) Dec 21 2018 Technically true. Doubtful that is pragmatically true once a program exc...
- Mike Franklin (16/21) Dec 21 2018 Now that web assembly has arrived, C++ is a perfectly suitable
- H. S. Teoh (21/42) Dec 21 2018 Although I agree with the sentiment that, in the long term, Javascript
- Atila Neves (8/21) Dec 22 2018 As true as a C program of the same size. They're just better than
- Walter Bright (7/12) Dec 26 2018 I didn't know that. But one can support "raw" pointers in a sandbox via
- luckoverthere (4/19) Dec 26 2018 C++/CLI is dead, long live C++/CX
- Walter Bright (9/11) Dec 20 2018 And create a host of other problems. Multiple alias this is multiple inh...
- Steven Schveighoffer (15/28) Dec 21 2018 The issues I've seen in bugzilla are how alias this overrides default
- Walter Bright (5/15) Dec 21 2018 The ones I reviewed do not have easy answers as to what the correct beha...
- Steven Schveighoffer (60/79) Dec 21 2018 Which ones?
- Steven Schveighoffer (4/9) Dec 21 2018 A simple way to put this is -- if the code would compile WITHOUT alias
- Steven Schveighoffer (5/12) Dec 21 2018 FYI, this already prints a compiler error, which is exactly the right
- H. S. Teoh (7/12) Dec 21 2018 It doesn't have to be. It can be treated as imports: if there's any
- Walter Bright (2/3) Dec 24 2018 See my response to Timon.
- 12345swordy (4/7) Dec 24 2018 My 2 cents is that D needs to allow custom implicit conversion
- H. S. Teoh (7/17) Dec 24 2018 the horrible mess in C++ caused by implicit conversions and the
- 12345swordy (7/13) Dec 24 2018 I understand his concerns. However it doesn't change the fact
- H. S. Teoh (7/17) Dec 24 2018 [...]
- 12345swordy (4/24) Dec 24 2018 If I were to write a DIP on this, I have to wait to see if
- Walter Bright (12/13) Dec 24 2018 You'd need very compelling use cases.
- H. S. Teoh (60/70) Dec 24 2018 Haha, I happen to have the same opinion on the above two examples as you
- Walter Bright (17/32) Dec 24 2018 On 12/24/2018 1:31 PM, H. S. Teoh wrote:
- H. S. Teoh (44/70) Dec 24 2018 Ah well, just because something is a nice piece of engineering, doesn't
- Walter Bright (2/4) Dec 24 2018 Not that I'm aware of. Of course, like C's gets(), it'll never go away.
- H. S. Teoh (7/13) Dec 24 2018 So you're saying that basically my unpopular/unconventional choice of
- bpr (3/9) Dec 25 2018 Likely true. Nothing ever goes away.
- 12345swordy (16/31) Dec 24 2018 A use case that pops in my head is to avoiding using inheritance
- Rubn (12/51) Dec 24 2018 When talking implicit conversion (at least in the same sense as
- 12345swordy (12/28) Dec 24 2018 Similar to how C# does it.
- jmh530 (9/16) Dec 25 2018 Instead of implicit conversions, what about using something like
- 12345swordy (4/5) Dec 25 2018 That is a completely different issue and has nothing to do with
- 12345swordy (3/18) Dec 24 2018 Oh btw Merry Christmas!
- Rubn (4/19) Dec 24 2018 I feel like D's operator overloading can be equally abused as
- H. S. Teoh (40/56) Dec 24 2018 Many things *can* be abused, but aren't because there's little reason
- Rubn (20/82) Dec 24 2018 Being able to and not having a reason to do it are two different
- Walter Bright (12/14) Dec 25 2018 If you want to make "+" non-commutative, you have to work a little harde...
- Rubn (35/52) Dec 25 2018 Not that hard at all, you just do operator overloading like
- Walter Bright (2/3) Dec 26 2018 The debates about it in the 1980s.
- Rubn (4/7) Dec 27 2018 So you are basing your opinion on debates from 40 years ago? What
- Neia Neutuladh (7/9) Dec 24 2018 There just aren't as many people thinking that abusing operator
- Walter Bright (10/30) Dec 20 2018 It does take space in C++ depending on the compiler and the circumstance...
- Nicholas Wilson (4/8) Dec 20 2018 Its nothing to do with C++. If you do struct "inheritance" with
- Walter Bright (3/6) Dec 20 2018 Ok.
- H. S. Teoh (7/16) Dec 20 2018 [...]
- 12345swordy (4/20) Dec 20 2018 When IgorStepanov quit disappearing on us.
- H. S. Teoh (9/31) Dec 20 2018 [...]
- 12345swordy (3/28) Dec 20 2018 Then DIP 66 have failed and needs to be rejected.
- H. S. Teoh (17/31) Dec 20 2018 [...]
- 12345swordy (7/40) Dec 20 2018 Do we have any means of contacting him? That seems like a job of
- H. S. Teoh (13/28) Dec 20 2018 [...]
- Timon Gehr (2/7) Dec 20 2018 But it's a solved problem. Just make `alias this` exactly like `import`.
- Walter Bright (12/13) Dec 20 2018 Imports don't have adjuster thunks, implicit cast issues, slicing, or em...
- rikki cattermole (4/22) Dec 20 2018 Type Declaration -> alias this [0 .. $]
- Timon Gehr (15/36) Dec 21 2018 Treat implicit casting with `alias this` like an invocation of an
- Walter Bright (26/59) Dec 21 2018 That depends on how it is specified. For example, should functions found...
- Manu (3/31) Dec 20 2018 Sounds like the original accepted DIP needs to be amended?
- Guillaume Piolat (12/13) Dec 21 2018 What happens is in D we often want:
- Walter Bright (4/8) Dec 20 2018 T.A. Cargill's famous paper about multiple inheritance:
I've long since become bored of this design decision. Is there good reason for it? Why should it be impossible to derive a struct? It can just be a sugar for an `alias this`, but for a case of simple inheritance, `alias this` can be tedious to spot and understand when reading the code. There's also the special case of an empty base-struct. I **constantly** have to do this: struct Derived { static if (Base.tupleof.length == 0) ref inout(Base) base() inout { return *cast(inout(Base)*)&this; } else Base base; alias base this; // the things... } If not that, then the derived class gets an aligned field of nothing populated by one byte of empty base struct. It also wastes the single `alias this` slot that we get in a no-multiple-alias-this world. As far as I can tell, the decision is arbitrary... can we move past this?
Dec 19 2018
On Thursday, 20 December 2018 at 01:40:02 UTC, Manu wrote:I've long since become bored of this design decision. Is there good reason for it? Why should it be impossible to derive a struct? It can just be a sugar for an `alias this`,Yes but another possible semantic for a struct inheritance list would be the structural conformance, i.e duck types, but this will never happen in D since we use constraints for that. This could even be used as a primitive, simple and clean template system, although restricted to struct/union: dummy struct Base { void required(); } struct Foo : Base { void required(){} } // we don't expect a Base as param, but something that's conform with Base, // i.e something that can be statically verified to have `void required();` void call( dummy Base base){} Which in D translates to much, really much verbose and complex code: struct Base { void required(); } struct Foo { void required(){} } void call(B)(B base) if (__traits(hasMember, B, "required") && isSomeFuncion(...) && is(ReturnType!(...) == void)) {} let's say if you want to be 100% exact because nowadays I tend not to use template constraints anymore excepted when they are needed for the correct dispatching to an overload, they are a loss of time otherwise (i know some will hate this alternative point of view... )
Dec 19 2018
On Wed, Dec 19, 2018 at 6:10 PM Basile B. via Digitalmars-d <digitalmars-d puremagic.com> wrote:On Thursday, 20 December 2018 at 01:40:02 UTC, Manu wrote:I think strong traits are a different thing, otherwise you're conflating syntax with class inheritance, and nobody will expect that. I mean, I love strong traits, but make them a proper thing. Your suggestion is just kinda weird and nobody would anticipate that. I see no good reason to collide with normal class inheritance syntax that way. And that said, I don't think your answer is a comment on *why* it's not possible today :) I'd like to know the reason it doesn't just work already.I've long since become bored of this design decision. Is there good reason for it? Why should it be impossible to derive a struct? It can just be a sugar for an `alias this`,Yes but another possible semantic for a struct inheritance list would be the structural conformance, i.e duck types, but this will never happen in D since we use constraints for that. This could even be used as a primitive, simple and clean template system, although restricted to struct/union: dummy struct Base { void required(); } struct Foo : Base { void required(){} } // we don't expect a Base as param, but something that's conform with Base, // i.e something that can be statically verified to have `void required();` void call( dummy Base base){} Which in D translates to much, really much verbose and complex code: struct Base { void required(); } struct Foo { void required(){} } void call(B)(B base) if (__traits(hasMember, B, "required") && isSomeFuncion(...) && is(ReturnType!(...) == void)) {} let's say if you want to be 100% exact because nowadays I tend not to use template constraints anymore excepted when they are needed for the correct dispatching to an overload, they are a loss of time otherwise (i know some will hate this alternative point of view... )
Dec 19 2018
On Thursday, 20 December 2018 at 01:40:02 UTC, Manu wrote:I've long since become bored of this design decision. Is there good reason for it? Why should it be impossible to derive a struct? It can just be a sugar for an `alias this`, but for a case of simple inheritance, `alias this` can be tedious to spot and understand when reading the code. There's also the special case of an empty base-struct. I **constantly** have to do this: struct Derived { static if (Base.tupleof.length == 0) ref inout(Base) base() inout { return *cast(inout(Base)*)&this; } else Base base; alias base this; // the things... } If not that, then the derived class gets an aligned field of nothing populated by one byte of empty base struct. It also wastes the single `alias this` slot that we get in a no-multiple-alias-this world. As far as I can tell, the decision is arbitrary... can we move past this?I imagine inheritance comes with things like being able to cast a Derived* to Base*. How do you delete a Base* without knowing it is derived from? Same goes for "virtual" (C++) functions. Virtual destructors and all that vtable stuff you'd normally get aren't used in struct. Instead you need to use the class type with the garbage collector or some hacky work around with scoped. But classes organize their data any way they want, so you need to use a struct as a shell. Not really a because it's not possible, but just like we don't a lot of other stuff, it's a design decision that was made. Gotta poke Walter and see if he's in the "feel's like he doesn't owe us or anyone an explanation" kind of mood or not.
Dec 19 2018
On 12/19/2018 5:40 PM, Manu wrote:I've long since become bored of this design decision. Is there good reason for it?`alias this` can alias to a function, that doesn't work very well with the base class syntax (you also use alias this to a function).Why should it be impossible to derive a struct?Because polymorphism makes little sense for a value type.static if (Base.tupleof.length == 0)static if (Base.sizeof == 0)then the derived classclass? struct? Dessert topping? Floor wax? https://www.youtube.com/watch?v=wPO8PqHGWFU (too bad youtube pulled the video part, it's just audio)
Dec 19 2018
On Wed, Dec 19, 2018 at 7:45 PM Walter Bright via Digitalmars-d <digitalmars-d puremagic.com> wrote:On 12/19/2018 5:40 PM, Manu wrote:Right, by necessity, because an empty struct member takes padded space in the aggregate. I think C++ gets the empty-base-class mechanic right; it doesn't take space. I'm demonstrating crappy code that appears extremely frequently in lieu. Perhaps you have a better suggestion?I've long since become bored of this design decision. Is there good reason for it?`alias this` can alias to a function, that doesn't work very well with the base class syntax (you also use alias this to a function).It's not really polymorphism without a vtable, just simple extension. `alias this` produces the same result, it's just more wordy, kinda ugly, and boilerplate-ey. It also hogs the `alias this` slot.Why should it be impossible to derive a struct?Because polymorphism makes little sense for a value type.> static if (Base.tupleof.length == 0) static if (Base.sizeof == 0)Empty struct has sizeof == 1 no? It certainly takes that many bytes as a member, and that 1 byte is naturally padded out to the alignment of the following member.
Dec 20 2018
On 12/20/18 3:15 AM, Manu wrote:On Wed, Dec 19, 2018 at 7:45 PM Walter Bright via Digitalmars-d <digitalmars-d puremagic.com> wrote:Yes, it does take 1 byte. I believe the reasoning was so it could have a unique address and be used in an array. It's the same in C++ as well, according to the Internet (except for the base class optimization allowance). Note that C++ compilers aren't *required* to implement this. The difference between inheritance and manual inheritance (i.e. alias this and a member), is that with true inheritance there is no member that has to have it's own distinct address, so it's allowed to take up 0 space But I would expect your boilerplate could be handled via mixin template pretty easily, then it becomes: struct Derived { mixin DeriveFrom!Base; } That it takes up the one alias this slot is a bummer, but really we should implement multiple-alias-this and that problem would be solved. -SteveOn 12/19/2018 5:40 PM, Manu wrote: > static if (Base.tupleof.length == 0) static if (Base.sizeof == 0)Empty struct has sizeof == 1 no? It certainly takes that many bytes as a member, and that 1 byte is naturally padded out to the alignment of the following member.
Dec 20 2018
On Thu, Dec 20, 2018 at 7:00 AM Steven Schveighoffer via Digitalmars-d <digitalmars-d puremagic.com> wrote:On 12/20/18 3:15 AM, Manu wrote:Right, but that's still pretty shit, and I still don't know what advantage it has? Now the pattern you have to look for to understand you are dealing with a derived type is even more bespoke; every code base will have a different expression for this, and people might do it differently in different cases. Every single person I've interacted with that's encountered D has been surprised by this. I'm not sure there's a good reason for it. I'm not saying the current method shouldn't exist, or that it's bad design or not useful. I'm just saying that BOTH should exist, and the syntax may just be sugar for simple, common, and expected aggregation. It can even call the member 'super', instead of some random name. `alias this` is great, but it's too manual, too much noise, and not searchable, which isn't great for the simple case which is deployed 99% of the time.On Wed, Dec 19, 2018 at 7:45 PM Walter Bright via Digitalmars-d <digitalmars-d puremagic.com> wrote:Yes, it does take 1 byte. I believe the reasoning was so it could have a unique address and be used in an array. It's the same in C++ as well, according to the Internet (except for the base class optimization allowance). Note that C++ compilers aren't *required* to implement this. The difference between inheritance and manual inheritance (i.e. alias this and a member), is that with true inheritance there is no member that has to have it's own distinct address, so it's allowed to take up 0 space But I would expect your boilerplate could be handled via mixin template pretty easily, then it becomes: struct Derived { mixin DeriveFrom!Base; }On 12/19/2018 5:40 PM, Manu wrote: > static if (Base.tupleof.length == 0) static if (Base.sizeof == 0)Empty struct has sizeof == 1 no? It certainly takes that many bytes as a member, and that 1 byte is naturally padded out to the alignment of the following member.That it takes up the one alias this slot is a bummer, but really we should implement multiple-alias-this and that problem would be solved.That's been accepted for years now... why is there no movement? Is the features as defined incompatible with the implementation of DMD?
Dec 20 2018
On Thu, Dec 20, 2018 at 10:20:54AM -0800, Manu via Digitalmars-d wrote:On Thu, Dec 20, 2018 at 7:00 AM Steven Schveighoffer via Digitalmars-d <digitalmars-d puremagic.com> wrote:[...]There has been multiple attempts to implement it, but none were persistent enough to see it through to the finish line. Maybe it's time to crowdfund a dedicated, full-time effort to bring this into a reality. T -- Latin's a dead language, as dead as can be; it killed off all the Romans, and now it's killing me! -- SchoolboyThat it takes up the one alias this slot is a bummer, but really we should implement multiple-alias-this and that problem would be solved.That's been accepted for years now... why is there no movement? Is the features as defined incompatible with the implementation of DMD?
Dec 20 2018
On 12/20/2018 10:38 AM, H. S. Teoh wrote:There has been multiple attempts to implement it, but none were persistent enough to see it through to the finish line.Nobody has figured out the semantics of single alias this, either (when faced with class inheritance). The bugzilla issues for it are ample evidence. MI is a Hansel and Gretel feature, where it appears to be all gingerbread and candy, but the witch inevitably appears to pop you in the oven. Other Hansel and Gretel features: 1. monkey patching 2. macros 3. implicit variable declaration 4. preprocessor
Dec 20 2018
On Thu., 20 Dec. 2018, 7:35 pm Walter Bright via Digitalmars-d < digitalmars-d puremagic.com wrote:On 12/20/2018 10:38 AM, H. S. Teoh wrote:I don't think I've ever wanted multiple inheritance in D, but I do want implicit conversions very often, and occasionally multiple implicit conversions.There has been multiple attempts to implement it, but none were persistent enough to see it through to the finish line.Nobody has figured out the semantics of single alias this, either (when faced with class inheritance). The bugzilla issues for it are ample evidence. MI is a Hansel and Gretel feature, where it appears to be all gingerbread and candy, but the witch inevitably appears to pop you in the oven. Other Hansel and Gretel features: 1. monkey patching 2. macros 3. implicit variable declaration 4. preprocessor
Dec 20 2018
On 12/20/2018 11:23 PM, Manu wrote:I don't think I've ever wanted multiple inheritance in D,That's what multiple alias this is.and occasionally multiple implicit conversions.Another feature that looks great in the small, but turns into a hopeless morass all too quickly. Even C++ gave up on that, which meant it was pretty bad :-) (Basically, nobody could figure out which overload was being called and why.)
Dec 21 2018
On Friday, December 21, 2018 4:28:21 AM MST Walter Bright via Digitalmars-d wrote:On 12/20/2018 11:23 PM, Manu wrote:Honestly, over time, I've come to dislike implicit conversions more and more. They cause enough stray bugs with the built-in types without even getting into the issues with user-defined types (issues with implicit conversions with character type and implicit slicing of static arrays come to mind in particular, though the problem is by no means just with them). But what gets particularly bad is templated code. It's trivial to write code that's supposed to work on any type that implictly converts to a particular type but then fail to actually do the conversion in the code, resulting in subtle bugs. The primary fix for this is to _always_ force the conversion if you're writing templated code that is supposed to work with an implicit conversion, but in general, it just works better that the conversion occur outside of the template. So, taking all of that into account, it becomes easy to start viewing implicit conversions in general as being a terrible idea. That being said, there are definitely times where implicit conversions are nice to have, and not having them can get pretty annoying. Also, casting is a blunt enough instrument that it can become easy to end up having explicit conversions that do the wrong thing (especially if the types involved get changed later without the code involving the case being updated). So, echewing implicit conversions can cause other problems (though on the whole, I do think that explicit conversions have far fewer problems - they just can get annoying sometimes). But over time I've become increasingly worried about having the ability to have multiple alias this-es on a type. There's no question that there are times when it would be really useful, but with all of the problems surrounding even a single alias this, having multiple alias this-es on a type starts looking really risky. As it is, I think that having even a single alias this should be done with caution and relatively rarely. And if we had the ability to have multiple alias this-es on a type, I would think that it should be used extremely rarely. But the very fact that it existed could have some nasty repercussions (especially for generic code). I don't know that that means that we shouldn't have the feature, but it definitley concerns me. - Jonathan M Davisand occasionally multiple implicit conversions.Another feature that looks great in the small, but turns into a hopeless morass all too quickly. Even C++ gave up on that, which meant it was pretty bad :-) (Basically, nobody could figure out which overload was being called and why.)
Dec 27 2018
On 12/27/18 3:15 PM, Jonathan M Davis wrote:On Friday, December 21, 2018 4:28:21 AM MST Walter Bright via Digitalmars-d wrote:We don't have to copy what C++ did.On 12/20/2018 11:23 PM, Manu wrote:and occasionally multiple implicit conversions.Another feature that looks great in the small, but turns into a hopeless morass all too quickly. Even C++ gave up on that, which meant it was pretty bad :-) (Basically, nobody could figure out which overload was being called and why.)Honestly, over time, I've come to dislike implicit conversions more and more. They cause enough stray bugs with the built-in types without even getting into the issues with user-defined types (issues with implicit conversions with character type and implicit slicing of static arrays come to mind in particular, though the problem is by no means just with them). But what gets particularly bad is templated code. It's trivial to write code that's supposed to work on any type that implictly converts to a particular type but then fail to actually do the conversion in the code, resulting in subtle bugs. The primary fix for this is to _always_ force the conversion if you're writing templated code that is supposed to work with an implicit conversion, but in general, it just works better that the conversion occur outside of the template. So, taking all of that into account, it becomes easy to start viewing implicit conversions in general as being a terrible idea.Well, implicit conversions of builtin types is not something a mere user can fix. I'd love to fix those problems, but the one DIP that was trying to fix a minuscule part of that was rejected for reasons that don't bode well for other parts. But in terms of implicit casting that's user defined -- those things are fixable (if they are a problem). Quite honestly, if alias this didn't exist, wrapping a type would be monstrously difficult. But it has to be implemented correctly (it's not right now).That being said, there are definitely times where implicit conversions are nice to have, and not having them can get pretty annoying. Also, casting is a blunt enough instrument that it can become easy to end up having explicit conversions that do the wrong thing (especially if the types involved get changed later without the code involving the case being updated).Speaking of that, I believe it's possible to have a casting library that is similar to C++'s casting system. We should create one.But over time I've become increasingly worried about having the ability to have multiple alias this-es on a type. There's no question that there are times when it would be really useful, but with all of the problems surrounding even a single alias this, having multiple alias this-es on a type starts looking really risky. As it is, I think that having even a single alias this should be done with caution and relatively rarely. And if we had the ability to have multiple alias this-es on a type, I would think that it should be used extremely rarely. But the very fact that it existed could have some nasty repercussions (especially for generic code). I don't know that that means that we shouldn't have the feature, but it definitley concerns me.Having multiple alias this's would not increase any of the existing problems really, it just would add one more wrinkle of ambiguity. But I think that behavior should be easily defined and understood. As for my own experience, I can't see myself using multiple alias this much at all, but it's definitely something that seems like an artificial limitation. -Steve
Dec 27 2018
On Thursday, 27 December 2018 at 20:15:04 UTC, Jonathan M Davis wrote:As it is, I think that having even a single alias this should be done with caution and relatively rarely. And if we had the ability to have multiple alias this-es on a type, I would think that it should be used extremely rarely. But the very fact that it existed could have some nasty repercussions (especially for generic code). I don't know that that means that we shouldn't have the feature, but it definitley concerns me. - Jonathan M DavisArguably, in a sense, we already have multiple alias this's. It just has to be done through 1 alias this per struct. struct A { int a; }; struct B { A a_; int b; alias a_ this; } struct C { B b_; int c; alias b_ this; } void main() { import std.stdio; C c; c.b = 10; c.a = 20; B b = c; A a = c; writeln( a, " ", b ); }
Dec 27 2018
On Fri, Dec 28, 2018 at 12:25:14AM +0000, luckoverthere via Digitalmars-d wrote:On Thursday, 27 December 2018 at 20:15:04 UTC, Jonathan M Davis wrote:[...]As it is, I think that having even a single alias this should be done with caution and relatively rarely. And if we had the ability to have multiple alias this-es on a type, I would think that it should be used extremely rarely. But the very fact that it existed could have some nasty repercussions (especially for generic code). I don't know that that means that we shouldn't have the feature, but it definitley concerns me.Arguably, in a sense, we already have multiple alias this's. It just has to be done through 1 alias this per struct. struct A { int a; }; struct B { A a_; int b; alias a_ this; } struct C { B b_; int c; alias b_ this; }[...] That's not multiple alias this, that's just a chain of alias this's. A linear class inheritance hierarchy is not equivalent to multiple inheritance. T -- The right half of the brain controls the left half of the body. This means that only left-handed people are in their right mind. -- Manoj Srivastava
Dec 27 2018
On Friday, 28 December 2018 at 00:36:15 UTC, H. S. Teoh wrote:On Fri, Dec 28, 2018 at 12:25:14AM +0000, luckoverthere via Digitalmars-d wrote:Indeed, keen observation! struct C { A a_; B b_; int c; alias a_ this; alias b_ this; } Sure you can arrange the structure differently and don't need to have one object contain another. Can have the same type for alias this'd. But in the context of the discussion of the comment I was replying to. It is possible to replicate the same feature of multiple alias this, as you can implicitly convert to multiple types.On Thursday, 27 December 2018 at 20:15:04 UTC, Jonathan M Davis wrote:[...]As it is, I think that having even a single alias this should be done with caution and relatively rarely. And if we had the ability to have multiple alias this-es on a type, I would think that it should be used extremely rarely. But the very fact that it existed could have some nasty repercussions (especially for generic code). I don't know that that means that we shouldn't have the feature, but it definitley concerns me.Arguably, in a sense, we already have multiple alias this's. It just has to be done through 1 alias this per struct. struct A { int a; }; struct B { A a_; int b; alias a_ this; } struct C { B b_; int c; alias b_ this; }[...] That's not multiple alias this, that's just a chain of alias this's. A linear class inheritance hierarchy is not equivalent to multiple inheritance. T
Dec 27 2018
On Fri, Dec 28, 2018 at 12:50:11AM +0000, luckoverthere via Digitalmars-d wrote: [...]struct C { A a_; B b_; int c; alias a_ this; alias b_ this; }[...] Compiler output: Error: there can be only one alias this Nope, still no multiple alias this. :-D T -- Designer clothes: how to cover less by paying more.
Dec 27 2018
On Friday, 21 December 2018 at 07:23:41 UTC, Manu wrote:On Thu., 20 Dec. 2018, 7:35 pm Walter Bright via Digitalmars-d < digitalmars-d puremagic.com wrote:I want implicit conversions here as well.What I don't want is this to be achievable via alias this, as you have no control over how it implicit case. I rather to do it via opCast. AlexOn 12/20/2018 10:38 AM, H. S. Teoh wrote:I don't think I've ever wanted multiple inheritance in D, but I do want implicit conversions very often, and occasionally multiple implicit conversions.There has been multiple attempts to implement it, but none were persistent enough to see it through to the finish line.Nobody has figured out the semantics of single alias this, either (when faced with class inheritance). The bugzilla issues for it are ample evidence. MI is a Hansel and Gretel feature, where it appears to be all gingerbread and candy, but the witch inevitably appears to pop you in the oven. Other Hansel and Gretel features: 1. monkey patching 2. macros 3. implicit variable declaration 4. preprocessor
Dec 21 2018
On Friday, 21 December 2018 at 03:33:05 UTC, Walter Bright wrote:On 12/20/2018 10:38 AM, H. S. Teoh wrote:I don't think any lisper has ever complained about Lisp macros - on the contrary, it's considered one of Lisp's killer features. It's a shame they're inextricably linked to the syntax (or lack thereof) and that nobody has yet figured out a good macro system that doesn't depend on S-expressions.There has been multiple attempts to implement it, but none were persistent enough to see it through to the finish line.Nobody has figured out the semantics of single alias this, either (when faced with class inheritance). The bugzilla issues for it are ample evidence. MI is a Hansel and Gretel feature, where it appears to be all gingerbread and candy, but the witch inevitably appears to pop you in the oven. Other Hansel and Gretel features: 1. monkey patching 2. macros 3. implicit variable declaration 4. preprocessor
Dec 21 2018
On 12/21/2018 2:42 AM, Atila Neves wrote:I don't think any lisper has ever complained about Lisp macros - on the contrary, it's considered one of Lisp's killer features. It's a shame they're inextricably linked to the syntax (or lack thereof) and that nobody has yet figured out a good macro system that doesn't depend on S-expressions.Probably because Lisp is unusable without macros, sort of like how C and C++ are unusable without the preprocessor. Lisp is a great language for its ideas, and is a fine language for research purposes. But somehow it just never catches on.
Dec 21 2018
On Friday, 21 December 2018 at 11:25:18 UTC, Walter Bright wrote:On 12/21/2018 2:42 AM, Atila Neves wrote:Lisp is perfectly usable without macros, it's just that it would never occur to anyone to do that. D is usable without `foreach`, but why would I program with that handicap? In Lisp, not using macros usually means typing "lambda" more than one would like. `foreach` isn't even the best example in D-land, `mixin` is. I think we can agree that `mixin` is a huge win for D. Lisp macros are like that, but much better.I don't think any lisper has ever complained about Lisp macros - on the contrary, it's considered one of Lisp's killer features. It's a shame they're inextricably linked to the syntax (or lack thereof) and that nobody has yet figured out a good macro system that doesn't depend on S-expressions.Probably because Lisp is unusable without macros,sort of like how C and C++ are unusable without the preprocessor.That's completely different - C/C++ have no way to reuse code other than the preprocessor. One technically could write a whole project without it, but it'd be madness. It's not at all like the Lisp case.Lisp is a great language for its ideas, and is a fine language for research purposes. But somehow it just never catches on.That depends on the definition of "catches on". Every Emacs user has to write Lisp (if they don't they might as well use notepad++); Common Lisp, Scheme and Clojure are all on Tiobe's top 50; Emacs Lisp and Clojure both outrank D in Github popularity (Common Lisp isn't that far behind). I dare say there are orders of magnitude more programmers using Lisp in the browser (via Clojurescript) than there are D programmers doing the same.
Dec 21 2018
On 12/21/2018 3:54 AM, Atila Neves wrote:On Friday, 21 December 2018 at 11:25:18 UTC, Walter Bright wrote:Technically true. Doubtful that is pragmatically true once a program exceeds a certain size.Probably because Lisp is unusable without macros,Lisp is perfectly usable without macros,In my subjective opinion, it is :-)sort of like how C and C++ are unusable without the preprocessor.That's completely different - C/C++ have no way to reuse code other than the preprocessor. One technically could write a whole project without it, but it'd be madness. It's not at all like the Lisp case.I've written Elisp extensions in Emacs, too. But they were all just a dozen or two lines. It never inspired me to write a larger program in it. I considered adding scripting to microEmacs, but I was going to use Javascript for that. :-) Lisp is an easy language to implement, document, and sandbox, making it handy for use as an embedded scripting language. Javascript takes months to implement by someone experienced writing compilers, making it not the first thing an IDE developer would try. D isn't any more suitable for in-browser code than C++ is. A native language with raw pointers would not be a good choice for an embeddable scripting language. Javascript has been incredibly successful as an embedded language in web pages.Lisp is a great language for its ideas, and is a fine language for research purposes. But somehow it just never catches on.That depends on the definition of "catches on". Every Emacs user has to write Lisp (if they don't they might as well use notepad++); Common Lisp, Scheme and Clojure are all on Tiobe's top 50; Emacs Lisp and Clojure both outrank D in Github popularity (Common Lisp isn't that far behind). I dare say there are orders of magnitude more programmers using Lisp in the browser (via Clojurescript) than there are D programmers doing the same.
Dec 21 2018
On Friday, 21 December 2018 at 21:42:35 UTC, Walter Bright wrote:D isn't any more suitable for in-browser code than C++ is. A native language with raw pointers would not be a good choice for an embeddable scripting language. Javascript has been incredibly successful as an embedded language in web pages.Now that web assembly has arrived, C++ is a perfectly suitable language for the browser. I'm predicting Javascript will become a legacy language for the web in 5 years. and they probably took me 20% of the time had I needed to write a eye-opening experience, and I'm never going back. There may still be a need for Javascript for a few things, but and other general purpose languages that can compile to web assembly is where it's at for the future of the web. And, I don't see why D can't be a major player there, as I know it already has been demonstrated to be: https://forum.dlang.org/post/zwmszfalyeprtyyhxfeq forum.dlang.org Mike
Dec 21 2018
On Fri, Dec 21, 2018 at 10:53:28PM +0000, Mike Franklin via Digitalmars-d wrote:On Friday, 21 December 2018 at 21:42:35 UTC, Walter Bright wrote:Although I agree with the sentiment that, in the long term, Javascript is a dead-end, I really doubt that it would become obsolete in 5 years. I'm expecting it will be more like 15-20 years, give or take.D isn't any more suitable for in-browser code than C++ is. A native language with raw pointers would not be a good choice for an embeddable scripting language. Javascript has been incredibly successful as an embedded language in web pages.Now that web assembly has arrived, C++ is a perfectly suitable language for the browser. I'm predicting Javascript will become a legacy language for the web in 5 years.they probably took me 20% of the time had I needed to write a backend experience, and I'm never going back.That's awesome, and in retrospect, not at all surprising, given the -- shall we call it, idiosyncrasies? -- of Javascript. While modern Javascript has come a long way since the early days of "on click, display an annoying flashing marquee", it has never been able to overcome the fundamental design limitations it inherited from those days. Writing non-trivial code in Javascript is an exercise in masochism, and I've had to *maintain* such code in the past. A nightmarish experience I would not wish on anyone.There may still be a need for Javascript for a few things, but not general purpose languages that can compile to web assembly is where it's at for the future of the web. And, I don't see why D can't be a major player there, as I know it already has been demonstrated to be: https://forum.dlang.org/post/zwmszfalyeprtyyhxfeq forum.dlang.org[...] While I still have qualms about the idea of running arbitrary code in a browser (no matter how encapsulated the sandbox is claimed to be), I *would* quite look forward to the day when I don't have to touch Javascript in order to deploy code on the web. Especially if said deployment can be done in D! T -- Never ascribe to malice that which is adequately explained by incompetence. -- Napoleon Bonaparte
Dec 21 2018
On Friday, 21 December 2018 at 21:42:35 UTC, Walter Bright wrote:On 12/21/2018 3:54 AM, Atila Neves wrote:As true as a C program of the same size. They're just better than not using them. I have difficulty not writing macros when I write Lisp, but then again I have difficulty not writing templates when I write C++ or D.On Friday, 21 December 2018 at 11:25:18 UTC, Walter Bright wrote:Technically true. Doubtful that is pragmatically true once a program exceeds a certain size.Probably because Lisp is unusable without macros,Lisp is perfectly usable without macros,D isn't any more suitable for in-browser code than C++ is. A native language with raw pointers would not be a good choice for an embeddable scripting language.And yet, people have been compiling C++ and running it in the browser for a while.Javascript has been incredibly successful as an embedded language in web pages.It has. But with webassembly its days might be numbered.
Dec 22 2018
On 12/22/2018 2:47 AM, Atila Neves wrote:I didn't know that. But one can support "raw" pointers in a sandbox via emulation. But then one loses the benefits of raw pointers. It doesn't change my opinion that C++ is unsuitable for in-browser work. As I recall, there is "managed C++" which was Microsoft getting C++ to work with CLI, but they did it by extensively modifying the language. https://en.wikipedia.org/wiki/C%2B%2B/CLID isn't any more suitable for in-browser code than C++ is. A native language with raw pointers would not be a good choice for an embeddable scripting language.And yet, people have been compiling C++ and running it in the browser for a while.
Dec 26 2018
On Wednesday, 26 December 2018 at 22:33:18 UTC, Walter Bright wrote:On 12/22/2018 2:47 AM, Atila Neves wrote:C++/CLI is dead, long live C++/CX https://en.wikipedia.org/wiki/C%2B%2B/CXI didn't know that. But one can support "raw" pointers in a sandbox via emulation. But then one loses the benefits of raw pointers. It doesn't change my opinion that C++ is unsuitable for in-browser work. As I recall, there is "managed C++" which was Microsoft getting C++ to work with CLI, but they did it by extensively modifying the language. https://en.wikipedia.org/wiki/C%2B%2B/CLID isn't any more suitable for in-browser code than C++ is. A native language with raw pointers would not be a good choice for an embeddable scripting language.And yet, people have been compiling C++ and running it in the browser for a while.
Dec 26 2018
On 12/20/2018 6:55 AM, Steven Schveighoffer wrote:really we should implement multiple-alias-this and that problem would be solved.And create a host of other problems. Multiple alias this is multiple inheritance with all of C++'s problems with it, and more, because then you wind up with two (count 'em, 2!) multiple inheritance hierarchies. Madness. Even single alias this has spawned a fair amount of wreckage in bugzilla, because people use it for multiple inheritance which it was never intended for. MI is just a bad idea. It's best to just think of another way to structure the data - even if you get it to work, it'll just confuse the poor schlub who has to maintain the code.
Dec 20 2018
On 12/20/18 10:08 PM, Walter Bright wrote:On 12/20/2018 6:55 AM, Steven Schveighoffer wrote:The issues I've seen in bugzilla are how alias this overrides default expected behavior of classes. In other words, if you have a base class and want to cast it to a derived, and the base class has an alias this, it stupidly tries the alias this, and won't even consider a dynamic cast. It's not madness so much as poor implementation. Saying there are bugs in the alias this implementation is not the same as saying the feature is problematic. All that is needed is a good definition of what takes precedence -- we already have that, it's just not implemented properly.really we should implement multiple-alias-this and that problem would be solved.And create a host of other problems. Multiple alias this is multiple inheritance with all of C++'s problems with it, and more, because then you wind up with two (count 'em, 2!) multiple inheritance hierarchies. Madness. Even single alias this has spawned a fair amount of wreckage in bugzilla, because people use it for multiple inheritance which it was never intended for.MI is just a bad idea. It's best to just think of another way to structure the data - even if you get it to work, it'll just confuse the poor schlub who has to maintain the code.But MI is not multiple alias-this. alias-this is more like an implicit cast, where as multiple inheritance has to deal with the diamond problem, and other issues (like the expectation of base types living at the same address as the derived one). Would you say that C++ operator conversions has all the same problems as MI? -Steve
Dec 21 2018
On 12/21/2018 11:08 AM, Steven Schveighoffer wrote:The ones I reviewed do not have easy answers as to what the correct behavior "ought" to be, and it certainly is not spec'ed in the specification.The issues I've seen in bugzilla are how alias this overrides default expectedbehavior of classes. In other words, if you have a base class and want to cast it to a derived, and the base class has an alias this, it stupidly tries the alias this, and won't even consider a dynamic cast. It's not madness so much as poor implementation. Saying there are bugs in the alias this implementation is not the same as saying the feature is problematic. All that is needed is a good definition of what takes precedence -- we already have that, it's just not implemented properly.But MI is not multiple alias-this.It fundamentally is. (Though I agree it doesn't have the virtual base "diamond inheritance" issue.)
Dec 21 2018
On 12/21/18 4:46 PM, Walter Bright wrote:On 12/21/2018 11:08 AM, Steven Schveighoffer wrote:Which ones? Fundamentally, alias this brings behavior for types where default behavior doesn't exist. For classes, casting to void * or another object is defined, so alias this should not override. Principal of least surprise. That's the only bug I've seen.The ones I reviewed do not have easy answers as to what the correct behavior "ought" to be, and it certainly is not spec'ed in the specification.The issues I've seen in bugzilla are how alias this overrides default expectedbehavior of classes. In other words, if you have a base class and want to cast it to a derived, and the base class has an alias this, it stupidly tries the alias this, and won't even consider a dynamic cast. It's not madness so much as poor implementation. Saying there are bugs in the alias this implementation is not the same as saying the feature is problematic. All that is needed is a good definition of what takes precedence -- we already have that, it's just not implemented properly.In terms of which alias this is used, we have leeway to define whatever we want. Alias this acts like inheritance, but it's NOT inheritance. We can say there is a specific order of precedence between the alias this'd items (I wouldn't recommend that), or we could say more than one alias this being usable in the same expression is an ambiguity error. I don't think the precedence rules are that complicated: 1. The type's members or base classes 2. The type's alias this'd members. Any ambiguities are a compiler error. 3. UFCS functions that accept the type or base classes. 4. UFCS functions that accept any alias this'd type. Any ambiguities are a compiler error. Unlike MI, there is a specific member you can use to disambiguate, which is way less clunky than MI, where you need a cast, or to name the type itself. My vision: void foo(int x) { writeln("foo int"); } void foo(T t) { writeln("foo T"); } void bar(int x) { writeln("bar int"); } void baz(int x) { writeln("baz int"); } void baz(T t) { writeln("baz T"); } void baz(S s) { writeln("baz S"); } void foobar(int x) { writeln("foobar int"); } void foobar(T t) { writeln("foobar T"); } struct T { void bar() { writeln("bar T"); } } struct S { int x; T t; alias this x; alias this t; void foo() { writeln("S");} } S s; s.foo(); // foo S s.bar(); // bar T; members take precedence over UFCS s.baz(); // baz S; main type takes precedence over alias this'd s.foobar(); // Error, both alias this'd have same precednece for UFCS s.x.foobar(); // foobar int s.t.foobar(); // foobar T Don't have the "both alias this'd have the same member" error, but you get the idea. And your example from earlier: class C : B { B b; alias b this; } Basically, the alias this b is never used, because C will always take precedence. If you think any of this is unintuitive, please let me know. -SteveBut MI is not multiple alias-this.It fundamentally is. (Though I agree it doesn't have the virtual base "diamond inheritance" issue.)
Dec 21 2018
On 12/21/18 5:23 PM, Steven Schveighoffer wrote:1. The type's members or base classes 2. The type's alias this'd members. Any ambiguities are a compiler error. 3. UFCS functions that accept the type or base classes. 4. UFCS functions that accept any alias this'd type. Any ambiguities are a compiler error.A simple way to put this is -- if the code would compile WITHOUT alias this, then that's what happens. -Steve
Dec 21 2018
On 12/21/18 5:23 PM, Steven Schveighoffer wrote:And your example from earlier: class C : B { B b; alias b this; }FYI, this already prints a compiler error, which is exactly the right behavior! Error: alias this is not reachable as C already converts to onlineapp.B -Steve
Dec 21 2018
On Fri, Dec 21, 2018 at 01:46:45PM -0800, Walter Bright via Digitalmars-d wrote:On 12/21/2018 11:08 AM, Steven Schveighoffer wrote:[...]It doesn't have to be. It can be treated as imports: if there's any question about what a symbol should resolve to, emit an ambiguity error. T -- It won't be covered in the book. The source code has to be useful for something, after all. -- Larry WallBut MI is not multiple alias-this.It fundamentally is. (Though I agree it doesn't have the virtual base "diamond inheritance" issue.)
Dec 21 2018
On 12/21/2018 2:43 PM, H. S. Teoh wrote:It can be treated as imports:See my response to Timon.
Dec 24 2018
On Monday, 24 December 2018 at 11:46:46 UTC, Walter Bright wrote:On 12/21/2018 2:43 PM, H. S. Teoh wrote:My 2 cents is that D needs to allow custom implicit conversion without using alias this.(You shouldn't have to rely on alias this, to get implicit conversations!)It can be treated as imports:See my response to Timon.
Dec 24 2018
On Mon, Dec 24, 2018 at 04:51:09PM +0000, 12345swordy via Digitalmars-d wrote:On Monday, 24 December 2018 at 11:46:46 UTC, Walter Bright wrote:On 12/21/2018 2:43 PM, H. S. Teoh wrote:My 2 cents is that D needs to allow custom implicit conversion without using alias this.(You shouldn't have to rely on alias this, to get implicit conversations!)It can be treated as imports:See my response to Timon.From what I understand, Walter dislikes implicit conversions because ofthe horrible mess in C++ caused by implicit conversions and the associated obfuscated tangle of rules that nobody except language lawyers would even begin to understand. T -- Старый друг лучше новых двух.
Dec 24 2018
On Monday, 24 December 2018 at 17:08:33 UTC, H. S. Teoh wrote:From what I understand, Walter dislikes implicit conversions because of the horrible mess in C++ caused by implicit conversions and the associated obfuscated tangle of rules that nobody except language lawyers would even begin to understand. TI understand his concerns. However it doesn't change the fact that people use alias this as way of implicit casting, and people desire custom implicit conversions! *** We can introduce implicit conversations without introducing the mess that is C++!*** Alex
Dec 24 2018
On Mon, Dec 24, 2018 at 05:54:45PM +0000, 12345swordy via Digitalmars-d wrote:On Monday, 24 December 2018 at 17:08:33 UTC, H. S. Teoh wrote:[...]From what I understand, Walter dislikes implicit conversions because of the horrible mess in C++ caused by implicit conversions and the associated obfuscated tangle of rules that nobody except language lawyers would even begin to understand.I understand his concerns. However it doesn't change the fact that people use alias this as way of implicit casting, and people desire custom implicit conversions! *** We can introduce implicit conversations without introducing the mess that is C++!***[...] If you can convince him, that would be great! T -- Designer clothes: how to cover less by paying more.
Dec 24 2018
On Monday, 24 December 2018 at 18:10:16 UTC, H. S. Teoh wrote:On Mon, Dec 24, 2018 at 05:54:45PM +0000, 12345swordy via Digitalmars-d wrote:If I were to write a DIP on this, I have to wait to see if R-Values is going to be accepted or not. AlexOn Monday, 24 December 2018 at 17:08:33 UTC, H. S. Teoh wrote:[...]From what I understand, Walter dislikes implicit conversions because of the horrible mess in C++ caused by implicit conversions and the associated obfuscated tangle of rules that nobody except language lawyers would even begin to understand.I understand his concerns. However it doesn't change the fact that people use alias this as way of implicit casting, and people desire custom implicit conversions! *** We can introduce implicit conversations without introducing the mess that is C++!***[...] If you can convince him, that would be great! T
Dec 24 2018
On 12/24/2018 10:10 AM, H. S. Teoh wrote:If you can convince him, that would be great!You'd need very compelling use cases. It's like adding more and more horsepower to a car. At some point, it doesn't make the car better. Or like operator overloading. C++ has much more expansive rules for operator overloading. They lead to clever programs, and some people swear by them, but are they *better* programs? For example, * iostreams * regex DSL https://pdfs.semanticscholar.org/e630/5f84bca36251fd5a4ffa5f00e0effc8aaa7d.pdf ? I don't buy it. I've never seen an elegant use of the more expansive power (even though many insist those two examples are elegant).
Dec 24 2018
On Mon, Dec 24, 2018 at 11:57:50AM -0800, Walter Bright via Digitalmars-d wrote: [...]Or like operator overloading. C++ has much more expansive rules for operator overloading. They lead to clever programs, and some people swear by them, but are they *better* programs? For example, * iostreams * regex DSL https://pdfs.semanticscholar.org/e630/5f84bca36251fd5a4ffa5f00e0effc8aaa7d.pdf ? I don't buy it. I've never seen an elegant use of the more expansive power (even though many insist those two examples are elegant).Haha, I happen to have the same opinion on the above two examples as you do. Iostream's (ab)use of << and >> contrary to their intended meaning is absolutely atrocious. The wrong precedence of << and >> (as far as I/O is concerned) leads to required parentheses where you don't expect them, with odd results if you forget. And a readability nightmare when you need to output an integer shifted by some amount (which << is output and which is bit shift?). Not to mention the whole hack on top of a patch on top of a festering bandage concept of I/O manipulators and other such "clever" ideas that focus on solving the wrong problem. The whole thing is a code smell, IMNSHO. Back when I still wrote C++, I avoided iostream like the plague and stuck with cstdio where possible. I've had to debug iostreams-based code before, and it made me cringe every time. And the regex DSL is just ... wow. It takes operator overloading abuse to whole new levels never before imagined. The "regexes" you write with this mess of a design resemble *nothing* like regexes, and had absolutely strange precedence rules due to the abuse of operators to mean things far removed from their usual meanings. And have you seen the error messages? Whoa. It's the epitome of everything that's wrong with C++. This kind of code is barely writable and basically unmaintainable. Two symptoms that point to fundamental problems in the whole design. D's std.regex.ctRegex, for all of its warts, lets you write things like: auto re = ctRegex!`(\w+) ((\w+)(\.(\w+))*)`; while offering the same (arguably better) benefits. Try to write the equivalent with that horrible C++ regex library, and it becomes crystal clear that the D version got it right, warts aside.[1] [1] (Like seriously, just last week I rewrote one of my programs to completely avoid std.regex, because the mere act of using a regex adds 5 *seconds* to the total compilation time. And it's not even a complicated regex to begin with. Though, to be fair, the fact that we're annoyed over seconds rather than minutes or, God forbid, hours, that would have been usual fare in complex C++ projects, is a testament to how far ahead D is in this respect, in spite of said warts.) I've also worked with C++ libraries that overload the comma operator... Oh yes, the evil comma operator plus absolutely evil abuse of operator overloading. Oy. This kind of every-man-for-himself operator overloading leads to unmaintainable code where any piece of syntax can mean absolutely *anything*, because you can overload anything and everything, and you cannot even remotely begin to guess what a piece of code actually does just by looking at it. You might have had a fighting chance if you could only trace the calls to their call targets, but thanks to the lovely C++ blend of overload resolution rules, Koenig lookup, SFINAE, and implicit conversions, you need to be a language lawyer just to figure that out. D got it right by restricting the overloading of <, >, ==, etc., to a couple of consistent functions, instead of C++'s encouraging abuse by allowing arbitrary, unrelated implementations of < and >, for example, while discouraging correct use by requiring excessive boilerplate to overload <, then >, then ==, then !=, then <= and >=, just to be sure you covered all the bases. But I suppose we should count our blessings, that the iostream authors didn't choose to overload < and > for I/O instead of << and >> (which you absolutely could, if you're bent on writing bad code), so there remains something to be appreciated here, I guess.</sarcasm> T -- Skill without imagination is craftsmanship and gives us many useful objects such as wickerwork picnic baskets. Imagination without skill gives us modern art. -- Tom Stoppard
Dec 24 2018
On 12/24/2018 1:31 PM, H. S. Teoh wrote: There are technical problems with iostreams as well, such as formatting options, and not being multi-threadable.And the regex DSL is just ... wow. It takes operator overloading abuse to whole new levels never before imagined.I've talked to David Abrahams about it. It is a nice piece of engineering, and he's very proud of it. But I was right in my assessment of the abuse of operator overloading, as this sort of thing has just never caught on in the C++ community. Another in the "too much power" category is you can throw any type in C++. Such as an `int`. I've never, ever seen any credible use of that. I'm not in the least surprised that the C++ standard library has an Exception class you're supposed to derive from and throw that.This kind of every-man-for-himself operator overloading leads to unmaintainable code where any piece of syntax can mean absolutely *anything*, because you can overload anything and everything, and you cannot even remotely begin to guess what a piece of code actually does just by looking at it. You might have had a fighting chance if you could only trace the calls to their call targets, but thanks to the lovely C++ blend of overload resolution rules, Koenig lookup, SFINAE, and implicit conversions, you need to be a language lawyer just to figure that out.Yeah, that about sums up my argument to David about it.But I suppose we should count our blessings, that the iostream authors didn't choose to overload < and > for I/O instead of << and >> (which you absolutely could, if you're bent on writing bad code), so there remains something to be appreciated here, I guess.</sarcasm>I hated iostreams since the 1980s, but it took about 15 years for the C++ community to gradually come around to the idea that it was a mistake. A feature shouldn't be merely "cool" or "great", especially considering all the features D already has. It needs to enable significantly better code to be written. Better as in more efficient, more understandable, safer, less brittle, less tendency for errors, etc. Note that I didn't say "less typing" (!).
Dec 24 2018
On Mon, Dec 24, 2018 at 02:30:57PM -0800, Walter Bright via Digitalmars-d wrote:On 12/24/2018 1:31 PM, H. S. Teoh wrote:[...]Ah well, just because something is a nice piece of engineering, doesn't necessarily mean it was a good idea in the first place!And the regex DSL is just ... wow. It takes operator overloading abuse to whole new levels never before imagined.I've talked to David Abrahams about it. It is a nice piece of engineering, and he's very proud of it. But I was right in my assessment of the abuse of operator overloading, as this sort of thing has just never caught on in the C++ community.Another in the "too much power" category is you can throw any type in C++. Such as an `int`. I've never, ever seen any credible use of that. I'm not in the least surprised that the C++ standard library has an Exception class you're supposed to derive from and throw that.I used to have a code library that standardized on throwing char* to string literals. It was a lazy man's way of having error messages that masqueraded as error codes / exceptions. Not my proudest moment of software design. :-D Though I'll say that the primary motivation for that was my C background, where everything is an int error code, and my being utterly fed up with code that just returned a non-descript -1 on every kind of failure, or worse, returning the return value of another function that returns an *incompatible* range of int error codes, in a totally inconsistent way (e.g., sometimes the function would return -1, or ERR_XYZ where ERR_* is a series of error codes defined in module A, and sometimes returning errno, which is incompatible with module A's error codes, all jammed into a single int return that the caller could not possibly hope to unambiguously decipher). Worst of all, when a problem occurred I'd get a message like "error -123" with zero hint as to what -123 even means. Having char* as an error code instead ensured (1) there's always a human-readable message you can get out of it, even if you couldn't otherwise interpret it; (2) since char* is unique in the space of string literals, you can freely mix error code returns and not have to worry about ambiguities (the dynamic linker will even "remap error codes" for you so errors from multiple libraries will never be confused for one another); (3) no memory allocation is needed -- at least if you stick to my scheme of returning only string literals. Of course, there are other issues with such a design, but it seemed like a good idea at the time. [...]I haven't been keeping up with C++ in any serious way ever since I found D; what's the replacement for iostreams these days? Or is it yet another one of those Irreversible Historical Accidents that's here to stay, in spite of acknowledged flaws, to be patched over by Yet More Language Complications that will make the language require a PhD specializing in C++ just so you can write correct code, since the "obvious" way to write C++ is wrong in more ways than you even knew existed?But I suppose we should count our blessings, that the iostream authors didn't choose to overload < and > for I/O instead of << andI hated iostreams since the 1980s, but it took about 15 years for the C++ community to gradually come around to the idea that it was a mistake.(which you absolutely could, if you're bent on writing bad code), so there remains something to be appreciated here, I guess.</sarcasm>A feature shouldn't be merely "cool" or "great", especially considering all the features D already has. It needs to enable significantly better code to be written. Better as in more efficient, more understandable, safer, less brittle, less tendency for errors, etc. Note that I didn't say "less typing" (!).Unfortunately, all of those points conflict with each other at some level, and it's not immediately obvious which blend of them represents the best balance. T -- VI = Visual Irritation
Dec 24 2018
On 12/24/2018 3:24 PM, H. S. Teoh wrote:I haven't been keeping up with C++ in any serious way ever since I found D; what's the replacement for iostreams these days?Not that I'm aware of. Of course, like C's gets(), it'll never go away.
Dec 24 2018
On Mon, Dec 24, 2018 at 03:28:08PM -0800, Walter Bright via Digitalmars-d wrote:On 12/24/2018 3:24 PM, H. S. Teoh wrote:So you're saying that basically my unpopular/unconventional choice of sticking with cstdio all these years was actually the right one?! Scary. T -- Answer: Because it breaks the logical sequence of discussion. / Question: Why is top posting bad?I haven't been keeping up with C++ in any serious way ever since I found D; what's the replacement for iostreams these days?Not that I'm aware of. Of course, like C's gets(), it'll never go away.
Dec 24 2018
On Monday, 24 December 2018 at 23:28:08 UTC, Walter Bright wrote:On 12/24/2018 3:24 PM, H. S. Teoh wrote:https://github.com/fmtlib/fmt ?I haven't been keeping up with C++ in any serious way ever since I found D; what's the replacement for iostreams these days?Not that I'm aware of. Of course, like C's gets(), it'll never go away.Likely true. Nothing ever goes away.
Dec 25 2018
On Monday, 24 December 2018 at 19:57:50 UTC, Walter Bright wrote:On 12/24/2018 10:10 AM, H. S. Teoh wrote:A use case that pops in my head is to avoiding using inheritance as that is not always ideal tool, when it comes to structs/class as you have no control on how it does implicit conversions. No Basic Event programming. No Design by Introspection. No Data Conversion in Regards to Passing Member Variables. You class/struct may end up with functions/variables that you don't want, which creates needless bloat. If you want to support multiple implicit conversion with the current features, then you need multiple alias this, which is not a good solution as A.) It is multiple inheritance. Which we both agree it is a terrible idea. B.) Multi alias this still hasn't been implemented already. *Throws table*If you can convince him, that would be great!You'd need very compelling use cases. It's like adding more and more horsepower to a car. At some point, it doesn't make the car better. Or like operator overloading. C++ has much more expansive rules for operator overloading. They lead to clever programs, and some people swear by them, but are they *better* programs? For example, * iostreams * regex DSL https://pdfs.semanticscholar.org/e630/5f84bca36251fd5a4ffa5f00e0effc8aaa7d.pdf ? I don't buy it. I've never seen an elegant use of the more expansive power (even though many insist those two examples are elegant).
Dec 24 2018
On Monday, 24 December 2018 at 23:06:26 UTC, 12345swordy wrote:On Monday, 24 December 2018 at 19:57:50 UTC, Walter Bright wrote:When talking implicit conversion (at least in the same sense as C++) you create a new object when doing an implicit conversion. How do you envision the implicit conversion would work?On 12/24/2018 10:10 AM, H. S. Teoh wrote:A use case that pops in my head is to avoiding using inheritance as that is not always ideal tool, when it comes to structs/class as you have no control on how it does implicit conversions.If you can convince him, that would be great!You'd need very compelling use cases. It's like adding more and more horsepower to a car. At some point, it doesn't make the car better. Or like operator overloading. C++ has much more expansive rules for operator overloading. They lead to clever programs, and some people swear by them, but are they *better* programs? For example, * iostreams * regex DSL https://pdfs.semanticscholar.org/e630/5f84bca36251fd5a4ffa5f00e0effc8aaa7d.pdf ? I don't buy it. I've never seen an elegant use of the more expansive power (even though many insist those two examples are elegant).No Basic Event programming.Why do you need implicit conversion for this ?No Design by Introspection. No Data Conversion in Regards to Passing Member Variables. You class/struct may end up with functions/variables that you don't want, which creates needless bloat.You could just use explicit conversion for this, if that's the case. Other than not having write 1 extra identifier there wouldn't be that much more benefit.If you want to support multiple implicit conversion with the current features, then you need multiple alias this, which is not a good solution as A.) It is multiple inheritance. Which we both agree it is a terrible idea. B.) Multi alias this still hasn't been implemented already. *Throws table*Idk, all this seems shakey. I avoid implicit conversion as much as possible in C++, the times I do use it usually is because of some other limitation in C++ that can be solved a different way in D. Some concrete examples would help though.
Dec 24 2018
On Monday, 24 December 2018 at 23:54:19 UTC, Rubn wrote:When talking implicit conversion (at least in the same sense as C++) you create a new object when doing an implicit conversion. How do you envision the implicit conversion would work?https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/implicitWhy do you need implicit conversion for this ?I meant that you can't program an event that runs every time an implicit conversion occurs.(Unless you hacked the compiler that does that for you...)You could just use explicit conversion for thisI am specifically talking about implicit conversions via inheritance and why it not an idea tool, as (Which I had said before) you have no control on how it does implicit conversions. I am not talking about explicit conversions here.... What limitations in C++ are you talking about? AlexIf you want to support multiple implicit conversion with the current features, then you need multiple alias this, which is not a good solution as A.) It is multiple inheritance. Which we both agree it is a terrible idea. B.) Multi alias this still hasn't been implemented already. *Throws table*Idk, all this seems shakey. I avoid implicit conversion as much as possible in C++, the times I do use it usually is because of some other limitation in C++ that can be solved a different way in D.
Dec 24 2018
On Tuesday, 25 December 2018 at 04:48:22 UTC, 12345swordy wrote:On Monday, 24 December 2018 at 23:54:19 UTC, Rubn wrote:Instead of implicit conversions, what about using something like __traits(compiles, cast(U) T.init) to check whether T can be explicitly casted to U? Then you could just create a canCast function that can detect whether it works or not. You'd still have to write a template function to check, but it works with anything. See https://run.dlang.io/is/CfpvUE[snip]I am specifically talking about implicit conversions via inheritance and why it not an idea tool, as (Which I had said before) you have no control on how it does implicit conversions. I am not talking about explicit conversions here.
Dec 25 2018
On Tuesday, 25 December 2018 at 15:03:14 UTC, jmh530 wrote:to check whether T can be explicitly casted to U?That is a completely different issue and has nothing to do with implicit conversion. -Alex
Dec 25 2018
On Monday, 24 December 2018 at 19:57:50 UTC, Walter Bright wrote:On 12/24/2018 10:10 AM, H. S. Teoh wrote:Oh btw Merry Christmas! AlexIf you can convince him, that would be great!You'd need very compelling use cases. It's like adding more and more horsepower to a car. At some point, it doesn't make the car better. Or like operator overloading. C++ has much more expansive rules for operator overloading. They lead to clever programs, and some people swear by them, but are they *better* programs? For example, * iostreams * regex DSL https://pdfs.semanticscholar.org/e630/5f84bca36251fd5a4ffa5f00e0effc8aaa7d.pdf ? I don't buy it. I've never seen an elegant use of the more expansive power (even though many insist those two examples are elegant).
Dec 24 2018
On Monday, 24 December 2018 at 19:57:50 UTC, Walter Bright wrote:On 12/24/2018 10:10 AM, H. S. Teoh wrote:I feel like D's operator overloading can be equally abused as C++'s operator overloading. There just aren't people doing that with D (yet).If you can convince him, that would be great!You'd need very compelling use cases. It's like adding more and more horsepower to a car. At some point, it doesn't make the car better. Or like operator overloading. C++ has much more expansive rules for operator overloading. They lead to clever programs, and some people swear by them, but are they *better* programs? For example, * iostreams * regex DSL https://pdfs.semanticscholar.org/e630/5f84bca36251fd5a4ffa5f00e0effc8aaa7d.pdf ? I don't buy it. I've never seen an elegant use of the more expansive power (even though many insist those two examples are elegant).
Dec 24 2018
On Tue, Dec 25, 2018 at 12:15:58AM +0000, Rubn via Digitalmars-d wrote:On Monday, 24 December 2018 at 19:57:50 UTC, Walter Bright wrote:[...]Many things *can* be abused, but aren't because there's little reason to. D forces you to use opEquals / opCmp for overloading the comparison operators, so at least the behaviour will be (somewhat) consistent no matter how you abuse it. There's also no comma operator for you to abuse. The arithmetic operators can still be abused, but there are also better and easier ways of achieving equivalent results by other means in D, so there's not much incentive to do something like that. For example, compile-time regexes can be achieved by using string mixins, retaining normal regex syntax, so there's not much reason to abuse arithmetic operators with unnatural syntax, just so you can implement compile-time regexes. While << and >> can theoretically still be overloaded iostream-style, D already removed one of the main motivations for ditching C's stdio.h, namely, that the various printf functions are variadic in a non-typesafe way. D actually has 3 different ways of achieving variadic functions, the most common of which is based on variadic templates and completely type-safe. Although some people are not a fan of std.format, it does serve its purpose, and has also been extended in powerful new ways in D (cf., the %(...%) array formatter). There's also the built-in ~ concatenation operator, which can be used for concatenating output strings, and std.conv.text, which formats a list of stuff, so there's less reasons for iostream-style << and >>. Not to mention UFCS, which could be used for chaining output function calls without needing to overload any operators, plus, combined with range-based code, gives you powerful new ways of writing I/O code that essentially marginalizes the utility of iostream-style code. So yeah, it's still *possible* to abuse operator overloading in D, but the incentives for doing that are pretty low, and there are many other nicer features with higher incentives that people are more liable to use instead. It's reminiscient of Walter's Boeing thing, about designing interfaces such that the way people are most likely to use it also happens to be the correct way, whereas the wrong way of doing things requires more effort and/or sticks out like a sore thumb, so people are less likely to attempt it. T -- They pretend to pay us, and we pretend to work. -- Russian sayingOr like operator overloading. C++ has much more expansive rules for operator overloading. They lead to clever programs, and some people swear by them, but are they *better* programs? For example, * iostreams * regex DSL https://pdfs.semanticscholar.org/e630/5f84bca36251fd5a4ffa5f00e0effc8aaa7d.pdf ? I don't buy it. I've never seen an elegant use of the more expansive power (even though many insist those two examples are elegant).I feel like D's operator overloading can be equally abused as C++'s operator overloading. There just aren't people doing that with D (yet).
Dec 24 2018
On Tuesday, 25 December 2018 at 00:40:13 UTC, H. S. Teoh wrote:On Tue, Dec 25, 2018 at 12:15:58AM +0000, Rubn via Digitalmars-d wrote:Being able to and not having a reason to do it are two different things. Someone is going to find a reason to use it and abuse it. Sure you can't overload equality and comma operators, but you can overload just about every other operator. You can easily make the "+" operator do something entirely different than addition. Same with any of the other operators. They can be used with any other type and can output any unrelated type they wish. That's not going to stick out like a sore thumb, and it isn't that much more difficult to do. I wouldn't exactly call this designing an "interface" as it isn't really an interface so much as a feature. I wouldn't say "correct" and "wrong". There's a lot of things in D that are the "correct" way to do something but are incredibly difficult to do and results in messy code. As an example, until very recently you had to write a hack if you wanted to deprecate a single enum value. More accurate words to use would be something a long the lines of "intended design". I mean I could bring up auto-decoding as well, would you say that's the "correct" way or merely the "intended design" falling flat on its' face ending up being incorrect.On Monday, 24 December 2018 at 19:57:50 UTC, Walter Bright wrote:[...]Many things *can* be abused, but aren't because there's little reason to. D forces you to use opEquals / opCmp for overloading the comparison operators, so at least the behaviour will be (somewhat) consistent no matter how you abuse it. There's also no comma operator for you to abuse. The arithmetic operators can still be abused, but there are also better and easier ways of achieving equivalent results by other means in D, so there's not much incentive to do something like that. For example, compile-time regexes can be achieved by using string mixins, retaining normal regex syntax, so there's not much reason to abuse arithmetic operators with unnatural syntax, just so you can implement compile-time regexes. While << and >> can theoretically still be overloaded iostream-style, D already removed one of the main motivations for ditching C's stdio.h, namely, that the various printf functions are variadic in a non-typesafe way. D actually has 3 different ways of achieving variadic functions, the most common of which is based on variadic templates and completely type-safe. Although some people are not a fan of std.format, it does serve its purpose, and has also been extended in powerful new ways in D (cf., the %(...%) array formatter). There's also the built-in ~ concatenation operator, which can be used for concatenating output strings, and std.conv.text, which formats a list of stuff, so there's less reasons for iostream-style << and >>. Not to mention UFCS, which could be used for chaining output function calls without needing to overload any operators, plus, combined with range-based code, gives you powerful new ways of writing I/O code that essentially marginalizes the utility of iostream-style code. So yeah, it's still *possible* to abuse operator overloading in D, but the incentives for doing that are pretty low, and there are many other nicer features with higher incentives that people are more liable to use instead. It's reminiscient of Walter's Boeing thing, about designing interfaces such that the way people are most likely to use it also happens to be the correct way, whereas the wrong way of doing things requires more effort and/or sticks out like a sore thumb, so people are less likely to attempt it. TOr like operator overloading. C++ has much more expansive rules for operator overloading. They lead to clever programs, and some people swear by them, but are they *better* programs? For example, * iostreams * regex DSL https://pdfs.semanticscholar.org/e630/5f84bca36251fd5a4ffa5f00e0effc8aaa7d.pdf ? I don't buy it. I've never seen an elegant use of the more expansive power (even though many insist those two examples are elegant).I feel like D's operator overloading can be equally abused as C++'s operator overloading. There just aren't people doing that with D (yet).
Dec 24 2018
On 12/24/2018 6:43 PM, Rubn wrote:You can easily make the "+" operator do something entirely different than addition.If you want to make "+" non-commutative, you have to work a little harder. I'm happy to see that D has successfully inculcated a culture that attempting to use operator overloading for non-arithmetic purposes is a code smell, rather than celebrating it as C++ does. It's like: #define BEGIN { #define END } is considered a smell in C (it didn't use to be, it took a while to stamp that out). We'll not be accepting such practices into the D standard library, etc., and will do what we can to discourage such. So yes, if you try hard enough, you can write execrable code. But you'll be on your own with it.
Dec 25 2018
On Tuesday, 25 December 2018 at 11:31:17 UTC, Walter Bright wrote:On 12/24/2018 6:43 PM, Rubn wrote:Not that hard at all, you just do operator overloading like normal. https://run.dlang.io/is/Jg8Jff struct Int { int value; this( int input ) { value = input; } Int opBinary(string op)(int a) const if ( op == "+" ) { return Int(value + a); } // Hell can make this return a different type and you // won't be even be able to do the comparison: (a + b) == (b + a) Int opBinaryRight(string op)(int a) const if ( op == "+" ) { return Int(value + a + 1); } } void main() { import std.stdio : writeln; const Int a = 5; const int b = 2; writeln(a + b, " == ", b + a); }You can easily make the "+" operator do something entirely different than addition.If you want to make "+" non-commutative, you have to work a little harder.I'm happy to see that D has successfully inculcated a culture that attempting to use operator overloading for non-arithmetic purposes is a code smell, rather than celebrating it as C++ does. It's like: #define BEGIN { #define END } is considered a smell in C (it didn't use to be, it took a while to stamp that out).What makes you think C++ celebrates it? You just point to one person that thinks it's a good idea. The C++ community has tens of thousands more users than D, there are going to be people that think it is a good idea.We'll not be accepting such practices into the D standard library, etc., and will do what we can to discourage such. So yes, if you try hard enough, you can write execrable code. But you'll be on your own with it.Sadly auto-decoding has already made it into the standard. I'm happy to say auto-decoding won't be making its way into the C++ standard :).
Dec 25 2018
On 12/25/2018 4:50 AM, Rubn wrote:What makes you think C++ celebrates it?The debates about it in the 1980s.
Dec 26 2018
On Thursday, 27 December 2018 at 01:53:32 UTC, Walter Bright wrote:On 12/25/2018 4:50 AM, Rubn wrote:So you are basing your opinion on debates from 40 years ago? What debates was D having in the 1980s?What makes you think C++ celebrates it?The debates about it in the 1980s.
Dec 27 2018
On Tue, 25 Dec 2018 00:15:58 +0000, Rubn wrote:I feel like D's operator overloading can be equally abused as C++'s operator overloading. There just aren't people doing that with D (yet).There just aren't as many people thinking that abusing operator overloading is a neat trick these days. I have seen one person using iostream style << in D, which is kind of scary. May as well just use opCall instead if you need one item printed per function call, like Tango did. (And there *are* good reasons for that -- it reduces overhead both at compile time and runtime.)
Dec 24 2018
On 12/20/2018 12:15 AM, Manu wrote:Right, by necessity, because an empty struct member takes padded space in the aggregate. I think C++ gets the empty-base-class mechanic right; it doesn't take space.It does take space in C++ depending on the compiler and the circumstance (it's rather complicated). D behaves like the associated C++ compiler in that regard - if it doesn't please file a bug report.I'm demonstrating crappy code that appears extremely frequently in lieu. Perhaps you have a better suggestion?It seems you have a workaround for what you want to do, and it's a simple paste job. You could probably accomplish the same thing with a mixin template.It's not really polymorphism without a vtable, just simple extension. `alias this` produces the same result, it's just more wordy, kinda ugly, and boilerplate-ey.Why should it be impossible to derive a struct?Because polymorphism makes little sense for a value type.It also hogs the `alias this` slot.C++ doesn't have alias this, so why would there be a slot for it?Not necessarily, see "empty base optimization". But you're right for this particular case. https://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Empty_Base_Optimization> static if (Base.tupleof.length == 0) static if (Base.sizeof == 0)Empty struct has sizeof == 1 no? It certainly takes that many bytes as a member,
Dec 20 2018
On Friday, 21 December 2018 at 03:04:13 UTC, Walter Bright wrote:On 12/20/2018 12:15 AM, Manu wrote:Its nothing to do with C++. If you do struct "inheritance" with alias this, because there is no multiple alias this, you can't then alias this the struct to something else.It also hogs the `alias this` slot.C++ doesn't have alias this, so why would there be a slot for it?
Dec 20 2018
On 12/20/2018 7:14 PM, Nicholas Wilson wrote:If you do struct "inheritance" with alias this, because there is no multiple alias this, you can't then alias this the struct to something else.Ok. I suggest using aggregation rather than attempting multiple inheritance.
Dec 20 2018
On Thu, Dec 20, 2018 at 12:15:53AM -0800, Manu via Digitalmars-d wrote:On Wed, Dec 19, 2018 at 7:45 PM Walter Bright via Digitalmars-d <digitalmars-d puremagic.com> wrote:[...][...] Sigh... when is multiple alias this ever going to happen?? T -- Being forced to write comments actually improves code, because it is easier to fix a crock than to explain it. -- G. SteeleIt's not really polymorphism without a vtable, just simple extension. `alias this` produces the same result, it's just more wordy, kinda ugly, and boilerplate-ey. It also hogs the `alias this` slot.Why should it be impossible to derive a struct?Because polymorphism makes little sense for a value type.
Dec 20 2018
On Thursday, 20 December 2018 at 15:29:50 UTC, H. S. Teoh wrote:On Thu, Dec 20, 2018 at 12:15:53AM -0800, Manu via Digitalmars-d wrote:When IgorStepanov quit disappearing on us. https://github.com/dlang/dmd/pull/8378 AlexOn Wed, Dec 19, 2018 at 7:45 PM Walter Bright via Digitalmars-d <digitalmars-d puremagic.com> wrote:[...][...] Sigh... when is multiple alias this ever going to happen?? TIt's not really polymorphism without a vtable, just simple extension. `alias this` produces the same result, it's just more wordy, kinda ugly, and boilerplate-ey. It also hogs the `alias this` slot.Why should it be impossible to derive a struct?Because polymorphism makes little sense for a value type.
Dec 20 2018
On Thu, Dec 20, 2018 at 03:44:34PM +0000, 12345swordy via Digitalmars-d wrote:On Thursday, 20 December 2018 at 15:29:50 UTC, H. S. Teoh wrote:[...] IIRC, that PR was blocked because of disagreements over how ambiguous symbols over multiple alias this types would be resolved. Somebody needs to come up with a DIP with well-defined semantics for all the details and corner cases before this can move forward. T -- "Maybe" is a strange word. When mom or dad says it it means "yes", but when my big brothers say it it means "no"! -- PJ jr.On Thu, Dec 20, 2018 at 12:15:53AM -0800, Manu via Digitalmars-d wrote:When IgorStepanov quit disappearing on us. https://github.com/dlang/dmd/pull/8378On Wed, Dec 19, 2018 at 7:45 PM Walter Bright via Digitalmars-d <digitalmars-d puremagic.com> wrote:[...][...] Sigh... when is multiple alias this ever going to happen?? TIt's not really polymorphism without a vtable, just simple extension. `alias this` produces the same result, it's just more wordy, kinda ugly, and boilerplate-ey. It also hogs the `alias this` slot.Why should it be impossible to derive a struct?Because polymorphism makes little sense for a value type.
Dec 20 2018
On Thursday, 20 December 2018 at 16:10:39 UTC, H. S. Teoh wrote:On Thu, Dec 20, 2018 at 03:44:34PM +0000, 12345swordy via Digitalmars-d wrote:Then DIP 66 have failed and needs to be rejected. AlexOn Thursday, 20 December 2018 at 15:29:50 UTC, H. S. Teoh wrote:[...] IIRC, that PR was blocked because of disagreements over how ambiguous symbols over multiple alias this types would be resolved. Somebody needs to come up with a DIP with well-defined semantics for all the details and corner cases before this can move forward. TOn Thu, Dec 20, 2018 at 12:15:53AM -0800, Manu via Digitalmars-d wrote:When IgorStepanov quit disappearing on us. https://github.com/dlang/dmd/pull/8378[...][...][...][...] Sigh... when is multiple alias this ever going to happen?? T
Dec 20 2018
On Thu, Dec 20, 2018 at 04:45:13PM +0000, 12345swordy via Digitalmars-d wrote:On Thursday, 20 December 2018 at 16:10:39 UTC, H. S. Teoh wrote:[...]On Thu, Dec 20, 2018 at 03:44:34PM +0000, 12345swordy via Digitalmars-d wrote:On Thursday, 20 December 2018 at 15:29:50 UTC, H. S. Teoh wrote:[...]Sigh... when is multiple alias this ever going to happen??[...]When IgorStepanov quit disappearing on us. https://github.com/dlang/dmd/pull/8378[...] IIRC, that PR was blocked because of disagreements over how ambiguous symbols over multiple alias this types would be resolved. Somebody needs to come up with a DIP with well-defined semantics for all the details and corner cases before this can move forward.Then DIP 66 have failed and needs to be rejected.[...] alias this PR. My bad. I see that this is a newer PR submitted just earlier this year. I don't know if it addressed the concerns raised here: https://forum.dlang.org/post/m74pg8$gl4$1 digitalmars.com which I assume would be required to pass scrutiny by W&A. But in any case, there was some feedback but Igor seems to have gone MIA. Hopefully he shows up again soon. I've been waiting for multiple alias this for years now. :-/ T -- Life begins when you can spend your spare time programming instead of watching television. -- Cal Keegan
Dec 20 2018
On Thursday, 20 December 2018 at 18:04:12 UTC, H. S. Teoh wrote:On Thu, Dec 20, 2018 at 04:45:13PM +0000, 12345swordy via Digitalmars-d wrote:Do we have any means of contacting him? That seems like a job of the current PR manager Nicholas Wilson. FFS do we need a crowed funding to finished the damn thing? It been years already, and we can't rely on a single guy who keeps disappearing for long periods of time. -AlexOn Thursday, 20 December 2018 at 16:10:39 UTC, H. S. Teoh wrote:[...]On Thu, Dec 20, 2018 at 03:44:34PM +0000, 12345swordy via Digitalmars-d wrote:On Thursday, 20 December 2018 at 15:29:50 UTC, H. S. Teoh wrote:[...][...][...]When IgorStepanov quit disappearing on us. https://github.com/dlang/dmd/pull/8378[...] IIRC, that PR was blocked because of disagreements over how ambiguous symbols over multiple alias this types would be resolved. Somebody needs to come up with a DIP with well-defined semantics for all the details and corner cases before this can move forward.Then DIP 66 have failed and needs to be rejected.[...] multiple alias this PR. My bad. I see that this is a newer PR submitted just earlier this year. I don't know if it addressed the concerns raised here: https://forum.dlang.org/post/m74pg8$gl4$1 digitalmars.com which I assume would be required to pass scrutiny by W&A. But in any case, there was some feedback but Igor seems to have gone MIA. Hopefully he shows up again soon. I've been waiting for multiple alias this for years now. :-/ T
Dec 20 2018
On Thu, Dec 20, 2018 at 06:13:28PM +0000, 12345swordy via Digitalmars-d wrote: [...][...]multiple alias this PR. My bad. I see that this is a newer PR submitted just earlier this year. I don't know if it addressed the concerns raised here: https://forum.dlang.org/post/m74pg8$gl4$1 digitalmars.com which I assume would be required to pass scrutiny by W&A. But in any case, there was some feedback but Igor seems to have gone MIA. Hopefully he shows up again soon. I've been waiting for multiple alias this for years now. :-/Do we have any means of contacting him? That seems like a job of the current PR manager Nicholas Wilson. FFS do we need a crowed funding to finished the damn thing? It been years already, and we can't rely on a single guy who keeps disappearing for long periods of time.[...] Maybe we should just crowdfund this thing. It's been far too long, and there have been too many failed attempts at it. Maybe past attempts were abandoned because it turned out to be far too much more work than was anticipated, and what it takes is somebody to get paid to dedicate their full time to slogging through all the tedious/complicated bits until it gets to the finish line. T -- Who told you to swim in Crocodile Lake without life insurance??
Dec 20 2018
On 20.12.18 17:10, H. S. Teoh wrote:IIRC, that PR was blocked because of disagreements over how ambiguous symbols over multiple alias this types would be resolved. Somebody needs to come up with a DIP with well-defined semantics for all the details and corner cases before this can move forward.But it's a solved problem. Just make `alias this` exactly like `import`.
Dec 20 2018
On 12/20/2018 7:21 PM, Timon Gehr wrote:But it's a solved problem. Just make `alias this` exactly like `import`.Imports don't have adjuster thunks, implicit cast issues, slicing, or empty base optimizations. Import lookup in a class is different because of the two-phase nature of it (people complained bitterly about the earlier single phase lookup). Import lookup doesn't have to conform to the relevant undocumented C++ ABI, either. (It was about a year of bug reports until I was finally able to match Microsoft C++'s MFC behavior for MI struct layout.) class C : B { B b; alias b this; } Now what? (This is not specified in the dlang spec.)
Dec 20 2018
On 21/12/2018 5:09 PM, Walter Bright wrote:On 12/20/2018 7:21 PM, Timon Gehr wrote:Type Declaration -> alias this [0 .. $] At declaration site or the alias this, if it is not free-of-issues, error. Say didn't we have a DIP that was accepted for multiple alias this?But it's a solved problem. Just make `alias this` exactly like `import`.Imports don't have adjuster thunks, implicit cast issues, slicing, or empty base optimizations. Import lookup in a class is different because of the two-phase nature of it (people complained bitterly about the earlier single phase lookup). Import lookup doesn't have to conform to the relevant undocumented C++ ABI, either. (It was about a year of bug reports until I was finally able to match Microsoft C++'s MFC behavior for MI struct layout.) class C : B { B b; alias b this; } Now what? (This is not specified in the dlang spec.)
Dec 20 2018
On 21.12.18 05:09, Walter Bright wrote:On 12/20/2018 7:21 PM, Timon Gehr wrote:Neither does `alias this`.But it's a solved problem. Just make `alias this` exactly like `import`.Imports don't have adjuster thunks,implicit cast issues,Treat implicit casting with `alias this` like an invocation of an imported function.slicing,`alias this` does not have the slicing problem because it can't return something that shares the vtable with the original reference but has a different layout.or empty base optimizations.With `alias this`, empty base optimization has to be done manually.Import lookup in a class is different because of the two-phase nature of it (people complained bitterly about the earlier single phase lookup). ...Why should it be different? It's a "look up names in one of those scopes" problem. Same problem, same solution.Import lookup doesn't have to conform to the relevant undocumented C++ ABI, either.> (It was about a year of bug reports until I was finally able to match Microsoft C++'s MFC behavior for MI struct layout.) ...Why would multiple `alias this` have to conform to any C++ ABIs?class C : B { B b; alias b this; } Now what? (This is not specified in the dlang spec.)This is a single alias this problem. But checking imports, this should give ambiguity errors by default (for both member access and implicit/explicit casting) and there should be a way to explicitly disambiguate.
Dec 21 2018
On 12/21/2018 5:48 AM, Timon Gehr wrote:On 21.12.18 05:09, Walter Bright wrote:That depends on how it is specified. For example, should functions found through 'alias this' go into the vtbl[]? (It's not a vacuous question, it has come up with people wanting that to happen. I said no.)On 12/20/2018 7:21 PM, Timon Gehr wrote:Neither does `alias this`.But it's a solved problem. Just make `alias this` exactly like `import`.Imports don't have adjuster thunks,It's not that simple. There are issues with what is considered a "better" match, several of which are in bugzilla w.r.t. alias this.implicit cast issues,Treat implicit casting with `alias this` like an invocation of an imported function.That all depends on how one defines how alias this lookup works wrt providing functions to be installed in the vtbl[].slicing,`alias this` does not have the slicing problem because it can't return something that shares the vtable with the original reference but has a different layout.That isn't how import lookup works today when import declarations appear in classes. It originally worked that way, but nobody understood it. I was UNABLE to explain that import lookup worked exactly like member lookup. I even showed the code which was the same code. But everyone, simply could not understand this and insisted it was behaving bizarrely. So now it is a much more complex 2 phase lookup that behaves "intuitively". It's a great lesson in how "obvious" and "intuitive" behavior for a person is anything but as an algorithm.Import lookup in a class is different because of the two-phase nature of it (people complained bitterly about the earlier single phase lookup). ...Why should it be different? It's a "look up names in one of those scopes" problem. Same problem, same solution.Because people can, will, and do (see Manu) use it to try to emulate struct inheritance for C++ structs.Import lookup doesn't have to conform to the relevant undocumented C++ ABI, either.> (It was about a year of bug reports until I was finally able to match Microsoft C++'s MFC behavior for MI struct layout.)Why would multiple `alias this` have to conform to any C++ ABIs?That isn't how imports work (the base class lookup takes precedence over import lookup). To sum up, the behavior of single alias this is not spec'ed, and there are a lot of decisions to make to tighten that up that are not obvious. All that would have to be done before any multiple alias this can be considered. The experience with MI in C++ was that a seemingly simple idea turned out to have a great deal of unexpected complexity, most of it turning up later. And worse, even when all that was eventually worked out and the implementation bugs fixed, the benefits of MI to programming pretty much failed to materialize.class C : B { B b; alias b this; } Now what? (This is not specified in the dlang spec.)This is a single alias this problem. But checking imports, this should give ambiguity errors by default (for both member access and implicit/explicit casting) and there should be a way to explicitly disambiguate.
Dec 21 2018
On Thu, Dec 20, 2018 at 8:10 AM H. S. Teoh via Digitalmars-d <digitalmars-d puremagic.com> wrote:On Thu, Dec 20, 2018 at 03:44:34PM +0000, 12345swordy via Digitalmars-d wrote:Sounds like the original accepted DIP needs to be amended?On Thursday, 20 December 2018 at 15:29:50 UTC, H. S. Teoh wrote:[...] IIRC, that PR was blocked because of disagreements over how ambiguous symbols over multiple alias this types would be resolved. Somebody needs to come up with a DIP with well-defined semantics for all the details and corner cases before this can move forward.On Thu, Dec 20, 2018 at 12:15:53AM -0800, Manu via Digitalmars-d wrote:When IgorStepanov quit disappearing on us. https://github.com/dlang/dmd/pull/8378On Wed, Dec 19, 2018 at 7:45 PM Walter Bright via Digitalmars-d <digitalmars-d puremagic.com> wrote:[...][...] Sigh... when is multiple alias this ever going to happen?? TIt's not really polymorphism without a vtable, just simple extension. `alias this` produces the same result, it's just more wordy, kinda ugly, and boilerplate-ey. It also hogs the `alias this` slot.Why should it be impossible to derive a struct?Because polymorphism makes little sense for a value type.
Dec 20 2018
On Thursday, 20 December 2018 at 03:42:08 UTC, Walter Bright wrote:Because polymorphism makes little sense for a value type.What happens is in D we often want: A - deterministic destruction AND B - reference semantics AND C - sub-typing (interfaces / alias this) `class` does B and C, and even A when emplaced, but not that easy to use. Don't work in -betterC. GC will call destructors which breaks (A) if we aren't careful. `struct` does A, B when wrapped, that not C very well.
Dec 21 2018
On 12/19/2018 5:40 PM, Manu wrote:It also wastes the single `alias this` slot that we get in a no-multiple-alias-this world. As far as I can tell, the decision is arbitrary... can we move past this?T.A. Cargill's famous paper about multiple inheritance: "Controversy: The Case Against Multiple Inheritance in C++" https://www.usenix.org/legacy/publications/compsystems/1991/win_cargill.pdf
Dec 20 2018