digitalmars.D - Can we just have struct inheritence already?
- Manu (19/19) Jun 09 2019 I am really really tired of this pattern:
- KnightMare (8/12) Jun 09 2019 +1
- Mike Parker (4/8) Jun 09 2019 Object slicing. It's a problem with inherited types when passed
- KnightMare (4/7) Jun 09 2019 in C++ this problem solved easy: cut data to base struct and u
- Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= (2/11) Jun 09 2019 Use private inheritance of base class.
- Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= (21/22) Jun 09 2019 Or add a feature that make subclass references const so that you
- KnightMare (3/10) Jun 09 2019 oops! C hasn't struct inheritance. my fault and excuse.
- Andre Pany (10/29) Jun 09 2019 Users would then also expect they can use the derived structures
- KnightMare (4/10) Jun 09 2019 not really. people will try to use keywords "virtual" or
- Exil (11/30) Jun 09 2019 You can just put the boiler plate code in a mixin template.
- Exil (11/30) Jun 09 2019 You can just put the boiler plate code in a mixin template.
- 12345swordy (2/21) Jun 09 2019 What is wrong with alias this?
- KnightMare (12/13) Jun 09 2019 in my mind "alias this" is a crutch that allow to move on, that
- KnightMare (3/4) Jun 09 2019 *your mind this is cool thing*
- SashaGreat (6/10) Jun 09 2019 Or you can:
- KnightMare (5/11) Jun 09 2019 people make mistakes that can't be changed.
- Jonathan M Davis (7/21) Jun 09 2019 This is a newsgroup which can also be accessed via a web interface and v...
- Exil (3/28) Jun 09 2019 Github also sends messages via email, you can even make replies
- Jonathan M Davis (14/45) Jun 09 2019 But no one gets those updates without looking at github, and even if the...
- Exil (9/60) Jun 09 2019 That's because emails aren't suited for this type of
- Andrei Alexandrescu (2/3) Jun 09 2019 Have at it!
- Jonathan M Davis (14/77) Jun 09 2019 Mailing lists have worked quite well for this type of communication for
- Timon Gehr (3/5) Jun 09 2019 Edit functionality is not "something better". It's perfectly fine that
- Andrei Alexandrescu (4/11) Jun 09 2019 Sadly it was meant as a generalized "is-a". Implementation botched that,...
- Mike Franklin (14/18) Jun 09 2019 I like the `alias this` feature quite a lot, but it does have a
- Mike Franklin (2/3) Jun 09 2019 Sorry, I mean resolution rules.
- Nick Sabalausky (Abscissa) (9/34) Jun 09 2019 Not necessarily objecting here, but does this pattern really come up all...
- Vladimir Panteleev (5/12) Jun 09 2019 Structs are always at least 1 byte in size, even when they
- Walter Bright (4/6) Jun 09 2019 The reason is so that each struct instance is at a unique address.
- Nicholas Wilson (3/12) Jun 09 2019 There is a (proposal?) for a no unique address attribute to
- Nicholas Wilson (15/17) Jun 09 2019 Found it:
- Walter Bright (2/24) Jun 10 2019 I didn't know about that attribute. Thanks for digging it up. Sheesh.
- Nicholas Wilson (3/5) Jun 10 2019 Touché.
- Nick Sabalausky (Abscissa) (3/18) Jun 10 2019 Would it really be a problem for the addresses of zero-byte structs to
- H. S. Teoh (14/33) Jun 10 2019 Probably, if people expect:
- Nick Sabalausky (Abscissa) (26/38) Jun 11 2019 Ehh, maybe, but since when does anyone ever check a D struct's address
- H. S. Teoh (29/60) Jun 11 2019 I wouldn't say it occurs to structs specifically, but in generic code,
- Exil (10/37) Jun 12 2019 Since you'd still have to "alias this" the alias, it would
- Jonathan M Davis (10/39) Jun 10 2019 There's also
- Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= (3/6) Jun 10 2019 Yes, empty base class optimization:
- Vladimir Panteleev (4/10) Jun 10 2019 What advantages does this provide? Surely it can't be more
- Walter Bright (7/11) Jun 10 2019 I don't remember all the rationale (30 years ago!), but a couple reasons...
- Vladimir Panteleev (15/21) Jun 11 2019 But... 0-length arrays in D are already 0 bytes in size.
- rikki cattermole (2/3) Jun 11 2019 Oh that's a neat trick, I just use a bool!
- Walter Bright (4/5) Jun 12 2019 Ok, you got me there.
- Vladimir Panteleev (9/14) Jun 13 2019 From the page:
- aliak (21/38) Jun 13 2019 Just for amusement, rust has ZSTs (zero sized types) and Empty
- Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= (9/13) Jun 13 2019 On 64 bit architectures you probably could write a custom malloc
- Patrick Schluter (3/11) Jun 13 2019 Especially if you use C allocation realloc() as calling it with
- Vladimir Panteleev (5/12) Jun 15 2019 When would that be a problem? Any pointer is a valid pointer for
- Vladimir Panteleev (4/12) Jun 15 2019 Oh, I guess it would be an issue if you tried to grow it back to
- Nick Sabalausky (Abscissa) (2/4) Jun 11 2019 By reading .length instead of performing an unnecessary division.
- H. S. Teoh (9/15) Jun 11 2019 +1. I never liked that nonsensical sizeof(array)/sizeof(array[0])
- Walter Bright (14/15) Jun 09 2019 Is your real complaint this:
- Manu (9/24) Jun 09 2019 That is indeed the feature that necessitates my 'solution', but `alias
- Walter Bright (3/34) Jun 10 2019 Are you using 'alias this' to try to do multiple inheritance? Please don...
- Manu (16/50) Jun 10 2019 Somehow this thread forked from my OP, I listed reasons in my second
- Walter Bright (3/4) Jun 10 2019 One possibility is that if the alias this is referring to a struct with ...
- Manu (10/14) Jun 10 2019 The struct exists as a member irrespective of the alias this.
- Walter Bright (2/3) Jun 10 2019 Is it specifically for C++ interop, or you just want the zero size?
- Manu (21/25) Jun 11 2019 It occurs frequently in C++ interop, but that's only because most of
- Walter Bright (2/33) Jun 11 2019 Can I ask again, in a different way, why do you need the 0 size?
- Manu (3/36) Jun 11 2019 To handle base structs with no members.
- Exil (4/52) Jun 11 2019 Kind of curious, what do you use a base class for that has no
- Manu (12/65) Jun 11 2019 Metaprogramming; it's a template argument.
- Andrei Alexandrescu (3/10) Jun 12 2019 Subtyping is not needed for metaprogramming. (C++'s awkward way of doing...
- Manu (32/42) Jun 13 2019 Overuse of `alias this` is not any better. `alias this` is relatively
- 12345swordy (4/69) Jun 13 2019 Wouldn't it be better to allow structs to implement static only
- Manu (5/8) Jun 13 2019 I don't know what that means? Like D `interface`, which is a pure
- 12345swordy (3/13) Jun 13 2019 Interface with only static functions and data members. No virtual
- Manu (4/18) Jun 13 2019 Well... right. We're talking about struct's here. struct's don't have
- 12345swordy (6/26) Jun 13 2019 I am saying that structs should be allow to inherent interfaces,
- Manu (8/35) Jun 13 2019 I think that's much more weird than struct's inheriting a struct... an
- Random D user (52/53) Jun 14 2019 I would define it as something like this:
- Walter Bright (3/6) Jun 12 2019 For the 3rd time, why do you need it to have 0 size? I don't know what y...
- Manu (14/20) Jun 12 2019 I hate wasting 8 bytes needlessly. Almost every struct I write is
- Walter Bright (3/27) Jun 18 2019 Have you considered using template mixins? Since you're using a base str...
- Ethan (8/18) Jun 18 2019 The ABI compatibility point really needs to be reiterated here.
- Walter Bright (13/22) Jun 18 2019 You can do this:
- Timon Gehr (4/31) Jun 18 2019 This works if Base and Derived are defined in the same module. Otherwise...
- Walter Bright (4/7) Jun 18 2019 That is correct, but with some care you can make it work, even if the mi...
- Manu (3/10) Jun 18 2019 I already have workarounds. That's not what this thread is about.
- John Colvin (13/27) Jun 25 2019 Not just my opinion, but what I perceive to be expected procedure
- Manu (4/31) Jun 18 2019 I mean, I love macro's as much as the next guy, and they're not at all
- Manu (18/40) Jun 12 2019 What are we so afraid of? I don't understand the resistance to this
- XavierAP (39/57) Jun 13 2019 Several topics have come up that imho all may have merit and
- Timon Gehr (10/20) Jun 13 2019 I think a lot of the default opposition to new features (especially if
- Walter Bright (10/14) Jun 18 2019 D has a TON of features. And yet every single day, people demand ever mo...
- Timon Gehr (8/19) Jun 18 2019 As far as I can tell, a lot of the incidental complexity is introduced
- Walter Bright (5/12) Jun 18 2019 You're absolutely right on that. I really want to encapsulate this stuff...
- Manu (18/32) Jun 18 2019 I'm pretty much just into feature uniformity at this stage. D's
- Olivier FAURE (9/33) Jun 18 2019 It might be because I write a lot less generic code than you do,
- XavierAP (39/71) Jun 19 2019 I'm not against struct inheritance... Even though I don't get or
- Walter Bright (3/4) Jun 18 2019 The more I've read about and studied concurrent programming issues, I te...
- Manu (7/11) Jun 18 2019 On the plus side, a working shared solution is only a couple of lines
- Olivier FAURE (5/8) Jun 18 2019 Quick question, have you considered the following syntax:
- Exil (6/11) Jun 13 2019 It doesn't become so obvious when you can implicitly convert to
- Manu (4/15) Jun 13 2019 So don't implicitly convert to the base type?
- Mike Parker (6/9) Jun 13 2019 So you want
- Manu (3/13) Jun 13 2019 Well, one's a class and the other's a struct, and that means what it mea...
- Mike Parker (5/16) Jun 14 2019 It means inconsistency, IMO, and a new violation of the principle
- XavierAP (17/20) Jun 14 2019 What is the benefit of
- XavierAP (14/23) Jun 14 2019 Moreover, even if your inheritance did not produce (static)
- Nick Sabalausky (Abscissa) (6/9) Jun 11 2019 In games programming, you frequently have (at least) one of two things:
- Walter Bright (2/3) Jun 12 2019 I'm curious what Manu's reason is. Does he have billions of them?
- Dejan Lekic (5/12) Jun 10 2019 +1
- Radu (14/33) Jun 11 2019 I like the idea! I use the `alias this` idiom everywhere, and it
- bioinfornatics (35/54) Jun 21 2019 That is a good idea (ahem… )but what about multiple derived
- Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= (24/29) Jun 21 2019 Listing all methods isn't very helpful, if that is the
- Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= (15/23) Jun 21 2019 In other words, you need static virtual methods. Perhaps a better
- bioinfornatics (15/45) Jun 21 2019 Yes you are right, previously I show one sample case, when you
- XavierAP (17/29) Jun 22 2019 If we want multiple inheritance or even virtual methods in
- bioinfornatics (10/41) Jun 24 2019 Thanks for your insight.
- Era Scarecrow (24/31) Jul 01 2019 Mhmm...
- Era Scarecrow (76/79) Jul 01 2019 And looking at my old notes... Might make it where the data size
I am really really tired of this pattern: struct DerivedStruct { static if (BaseStruct.tupleof.length > 0) BaseStruct base; else ref inout(BaseStruct) base() inout { return *cast(inout(BaseStruct)*)&this; } alias base this; // derived members //... } Imagine if we could just write: struct DerivedStruct : BaseStruct { // derived members //... } Just imagine!
Jun 09 2019
On Sunday, 9 June 2019 at 08:05:34 UTC, Manu wrote:struct DerivedStruct : BaseStruct { // derived members } Just imagine!+1 what is the problem not doing this? copying is not to difficult: blit and call postblit for all members if they have it. what the problem i forgot? you want to make better C, so make code familiar for C-users. why need this problems out of the blue?
Jun 09 2019
On Sunday, 9 June 2019 at 08:19:46 UTC, KnightMare wrote:what is the problem not doing this? copying is not to difficult: blit and call postblit for all members if they have it. what the problem i forgot?Object slicing. It's a problem with inherited types when passed by value. https://stackoverflow.com/questions/274626/what-is-object-slicing#274636
Jun 09 2019
On Sunday, 9 June 2019 at 08:39:09 UTC, Mike Parker wrote:Object slicing. It's a problem with inherited types when passed by value. https://stackoverflow.com/questions/274626/what-is-object-slicing#274636in C++ this problem solved easy: cut data to base struct and u cant call methods of derived struct. nobody asks virtuals in struct
Jun 09 2019
On Sunday, 9 June 2019 at 08:39:09 UTC, Mike Parker wrote:On Sunday, 9 June 2019 at 08:19:46 UTC, KnightMare wrote:Use private inheritance of base class.what is the problem not doing this? copying is not to difficult: blit and call postblit for all members if they have it. what the problem i forgot?Object slicing. It's a problem with inherited types when passed by value. https://stackoverflow.com/questions/274626/what-is-object-slicing#274636
Jun 09 2019
On Sunday, 9 June 2019 at 11:31:46 UTC, Ola Fosheim Grøstad wrote:Use private inheritance of base class.Or add a feature that make subclass references const so that you cannot assign to just the base class, unless the subclass explicitly allows it. Many possibilities for preventing assignment to base class only by using static typing. Of course, it has to be thought through. A third option is to provide "tagged" struct where a classifier function can determine the object type and pick the right "virtual" assignment operator (using a switch statement internally). A fourth option is to prevent sub-structs from overriding methods in the base struct and forbid assignment to be sub-struct dependent. A fifth option would be to have abstract base structs that cannot be instantiated, and make it so it has no default methods/operators. I assume this would allow multiple inheritance of abstract base structs. You could create new abstract base structs that inherits from other abstract base structs that are non-referencable outside the abstract base struct (so that you can resolve name collisions).
Jun 09 2019
On Sunday, 9 June 2019 at 08:19:46 UTC, KnightMare wrote:On Sunday, 9 June 2019 at 08:05:34 UTC, Manu wrote:oops! C hasn't struct inheritance. my fault and excuse. but it simple comfortable feature.struct DerivedStruct : BaseStruct { // derived members } Just imagine!+1 you want to make better C, so make code familiar for C-users.
Jun 09 2019
On Sunday, 9 June 2019 at 08:05:34 UTC, Manu wrote:I am really really tired of this pattern: struct DerivedStruct { static if (BaseStruct.tupleof.length > 0) BaseStruct base; else ref inout(BaseStruct) base() inout { return *cast(inout(BaseStruct)*)&this; } alias base this; // derived members //... } Imagine if we could just write: struct DerivedStruct : BaseStruct { // derived members //... } Just imagine!Users would then also expect they can use the derived structures in places where there ancestors are expected, similar like with classes;) And also they can overload the functions of this structures. Then we need to add a monitor field to all structures to enabled it. It seems like a small change, but opens a huge area of problems. Kind regards Andre
Jun 09 2019
On Sunday, 9 June 2019 at 08:31:40 UTC, Andre Pany wrote:Users would then also expect they can use the derived structures in places where there ancestors are expected, similar like with classes;) And also they can overload the functions of this structures. Then we need to add a monitor field to all structures to enabled it.not really. people will try to use keywords "virtual" or "override" and compiler will say/stop it. enough to get burned once.
Jun 09 2019
On Sunday, 9 June 2019 at 08:05:34 UTC, Manu wrote:I am really really tired of this pattern: struct DerivedStruct { static if (BaseStruct.tupleof.length > 0) BaseStruct base; else ref inout(BaseStruct) base() inout { return *cast(inout(BaseStruct)*)&this; } alias base this; // derived members //... } Imagine if we could just write: struct DerivedStruct : BaseStruct { // derived members //... } Just imagine!You can just put the boiler plate code in a mixin template. mixin template BaseAs(T) { static if(T.tupleof.length > 0) T base; else ref inout(T) base() inout { return *cast(inout(T)*)&this; } alias base this; } struct DerivedStruct { mixin BaseAs!BaseStruct; }
Jun 09 2019
On Sunday, 9 June 2019 at 08:05:34 UTC, Manu wrote:I am really really tired of this pattern: struct DerivedStruct { static if (BaseStruct.tupleof.length > 0) BaseStruct base; else ref inout(BaseStruct) base() inout { return *cast(inout(BaseStruct)*)&this; } alias base this; // derived members //... } Imagine if we could just write: struct DerivedStruct : BaseStruct { // derived members //... } Just imagine!You can just put the boiler plate code in a mixin template. mixin template BaseAs(T) { static if(T.tupleof.length > 0) T base; else ref inout(T) base() inout { return *cast(inout(T)*)&this; } alias base this; } struct DerivedStruct { mixin BaseAs!BaseStruct; }
Jun 09 2019
On Sunday, 9 June 2019 at 08:05:34 UTC, Manu wrote:I am really really tired of this pattern: struct DerivedStruct { static if (BaseStruct.tupleof.length > 0) BaseStruct base; else ref inout(BaseStruct) base() inout { return *cast(inout(BaseStruct)*)&this; } alias base this; // derived members //... } Imagine if we could just write: struct DerivedStruct : BaseStruct { // derived members //... } Just imagine!What is wrong with alias this?
Jun 09 2019
On Sunday, 9 June 2019 at 16:45:18 UTC, 12345swordy wrote:What is wrong with alias this?in my mind "alias this" is a crutch that allow to move on, that tries to replace "has-a" with "is-a" and at the same time introduces an implicit conversion operator. last one can be alone: decimal to double with no inheritance. in your my its cool thing and "let me sign your cast". well, just two different points of view at one thing. BUT in case where I want "is-a" from one type and implicit cast to another my point became more correct. BUT I can't think of an example right now, maybe no such example at all. BUT I still has more control in my hands with is-a/has-a and implicit opCast(if it will be added).
Jun 09 2019
On Sunday, 9 June 2019 at 17:09:44 UTC, KnightMare wrote:in your my its cool thing and "let me sign your cast".*your mind this is cool thing* PS need to allow edit post for 5min at at least
Jun 09 2019
On Sunday, 9 June 2019 at 17:11:37 UTC, KnightMare wrote:On Sunday, 9 June 2019 at 17:09:44 UTC, KnightMare wrote:Or you can: 1) Revise it better before posting. 2) If you use e-mail instead of WEB Front-End, some e-mail services and applications (Like Thunderbird) allows you to hold it for some time before sending.in your my its cool thing and "let me sign your cast".*your mind this is cool thing* PS need to allow edit post for 5min at at least
Jun 09 2019
On Sunday, 9 June 2019 at 17:26:40 UTC, SashaGreat wrote:people make mistakes that can't be changed. 1) please dont write AI for people control system :) 2) too complicated. my suggestion (allow to edit post in next 5mins) is more humane.PS need to allow edit post for 5min at at leastOr you can: 1) Revise it better before posting. 2) If you use e-mail instead of WEB Front-End, some e-mail services and applications (Like Thunderbird) allows you to hold it for some time before sending.
Jun 09 2019
On Sunday, June 9, 2019 11:35:28 AM MDT KnightMare via Digitalmars-d wrote:On Sunday, 9 June 2019 at 17:26:40 UTC, SashaGreat wrote:This is a newsgroup which can also be accessed via a web interface and via a mailing list. Once a message has been sent, it's been sent. It immediately goes out to everyone over the various interfaces, and it wouldn't make any more sense to try to edit your message after sending it than it would to try to edit an e-mail after you sent it to hundreds of people. - Jonathan M Davispeople make mistakes that can't be changed. 1) please dont write AI for people control system :) 2) too complicated. my suggestion (allow to edit post in next 5mins) is more humane.PS need to allow edit post for 5min at at leastOr you can: 1) Revise it better before posting. 2) If you use e-mail instead of WEB Front-End, some e-mail services and applications (Like Thunderbird) allows you to hold it for some time before sending.
Jun 09 2019
On Sunday, 9 June 2019 at 17:57:05 UTC, Jonathan M Davis wrote:On Sunday, June 9, 2019 11:35:28 AM MDT KnightMare via Digitalmars-d wrote:Github also sends messages via email, you can even make replies by email. You can still edit them afterwards though.On Sunday, 9 June 2019 at 17:26:40 UTC, SashaGreat wrote:This is a newsgroup which can also be accessed via a web interface and via a mailing list. Once a message has been sent, it's been sent. It immediately goes out to everyone over the various interfaces, and it wouldn't make any more sense to try to edit your message after sending it than it would to try to edit an e-mail after you sent it to hundreds of people. - Jonathan M Davispeople make mistakes that can't be changed. 1) please dont write AI for people control system :) 2) too complicated. my suggestion (allow to edit post in next 5mins) is more humane.PS need to allow edit post for 5min at at leastOr you can: 1) Revise it better before posting. 2) If you use e-mail instead of WEB Front-End, some e-mail services and applications (Like Thunderbird) allows you to hold it for some time before sending.
Jun 09 2019
On Sunday, June 9, 2019 12:19:34 PM MDT Exil via Digitalmars-d wrote:On Sunday, 9 June 2019 at 17:57:05 UTC, Jonathan M Davis wrote:But no one gets those updates without looking at github, and even if they did, it would have to be via a new e-mail, cluttering things up. It's not possible for anyone to edit their message on github and then have the e-mails that everyone received update. The e-mails from github serve as notifications of what's on the website, not as the primary means of communication. And for D, the web interface is _not_ what controls the data. It's a client just like my e-mail client is and just like Walter's newsgroup client is. So, all it can edit is its local cache, which would make it out-of-sync with everyone else. Or it could send out a second message - which is exactly what you have to do right now. And because that's what you have to do, it doesn't give the false impression that you can edit previously sent messages. - Jonathan M DavisOn Sunday, June 9, 2019 11:35:28 AM MDT KnightMare via Digitalmars-d wrote:Github also sends messages via email, you can even make replies by email. You can still edit them afterwards though.On Sunday, 9 June 2019 at 17:26:40 UTC, SashaGreat wrote:This is a newsgroup which can also be accessed via a web interface and via a mailing list. Once a message has been sent, it's been sent. It immediately goes out to everyone over the various interfaces, and it wouldn't make any more sense to try to edit your message after sending it than it would to try to edit an e-mail after you sent it to hundreds of people. - Jonathan M Davispeople make mistakes that can't be changed. 1) please dont write AI for people control system :) 2) too complicated. my suggestion (allow to edit post in next 5mins) is more humane.PS need to allow edit post for 5min at at leastOr you can: 1) Revise it better before posting. 2) If you use e-mail instead of WEB Front-End, some e-mail services and applications (Like Thunderbird) allows you to hold it for some time before sending.
Jun 09 2019
On Sunday, 9 June 2019 at 18:43:01 UTC, Jonathan M Davis wrote:On Sunday, June 9, 2019 12:19:34 PM MDT Exil via Digitalmars-d wrote:That's because emails aren't suited for this type of communication. If you want to use emails, then yes you would then receive a second email. But if someone needs to make a correction anyways, they will need to send a second email as well. This not only clutters up the email but also the website as well. Which is what we have now.On Sunday, 9 June 2019 at 17:57:05 UTC, Jonathan M Davis wrote:But no one gets those updates without looking at github, and even if they did, it would have to be via a new e-mail, cluttering things up. It's not possible for anyone to edit their message on github and then have the e-mails that everyone received update. The e-mails from github serve as notifications of what's on the website, not as the primary means of communication.On Sunday, June 9, 2019 11:35:28 AM MDT KnightMare via Digitalmars-d wrote:Github also sends messages via email, you can even make replies by email. You can still edit them afterwards though.On Sunday, 9 June 2019 at 17:26:40 UTC, SashaGreat wrote:This is a newsgroup which can also be accessed via a web interface and via a mailing list. Once a message has been sent, it's been sent. It immediately goes out to everyone over the various interfaces, and it wouldn't make any more sense to try to edit your message after sending it than it would to try to edit an e-mail after you sent it to hundreds of people. - Jonathan M Davispeople make mistakes that can't be changed. 1) please dont write AI for people control system :) 2) too complicated. my suggestion (allow to edit post in next 5mins) is more humane.PS need to allow edit post for 5min at at leastOr you can: 1) Revise it better before posting. 2) If you use e-mail instead of WEB Front-End, some e-mail services and applications (Like Thunderbird) allows you to hold it for some time before sending.And for D, the web interface is _not_ what controls the data. It's a client just like my e-mail client is and just like Walter's newsgroup client is. So, all it can edit is its local cache, which would make it out-of-sync with everyone else. Or it could send out a second message - which is exactly what you have to do right now. And because that's what you have to do, it doesn't give the false impression that you can edit previously sent messages. - Jonathan M DavisAnd? This is set in stone? There's no way to implement something better?
Jun 09 2019
On 6/9/19 2:52 PM, Exil wrote:And? This is set in stone? There's no way to implement something better?Have at it!
Jun 09 2019
On Sunday, June 9, 2019 12:52:20 PM MDT Exil via Digitalmars-d wrote:On Sunday, 9 June 2019 at 18:43:01 UTC, Jonathan M Davis wrote:Mailing lists have worked quite well for this type of communication for decades. So have newsgroups. And if you just reread what you're posting before you post it, you can avoid needing to edit it or send a response to your message to correct it. As it is, only a small percentage of posts in this newsgroup end up with the poster replying to correct their post.On Sunday, June 9, 2019 12:19:34 PM MDT Exil via Digitalmars-d wrote:That's because emails aren't suited for this type of communication. If you want to use emails, then yes you would then receive a second email. But if someone needs to make a correction anyways, they will need to send a second email as well. This not only clutters up the email but also the website as well. Which is what we have now.On Sunday, 9 June 2019 at 17:57:05 UTC, Jonathan M Davis wrote:But no one gets those updates without looking at github, and even if they did, it would have to be via a new e-mail, cluttering things up. It's not possible for anyone to edit their message on github and then have the e-mails that everyone received update. The e-mails from github serve as notifications of what's on the website, not as the primary means of communication.On Sunday, June 9, 2019 11:35:28 AM MDT KnightMare via Digitalmars-d wrote:Github also sends messages via email, you can even make replies by email. You can still edit them afterwards though.On Sunday, 9 June 2019 at 17:26:40 UTC, SashaGreat wrote:This is a newsgroup which can also be accessed via a web interface and via a mailing list. Once a message has been sent, it's been sent. It immediately goes out to everyone over the various interfaces, and it wouldn't make any more sense to try to edit your message after sending it than it would to try to edit an e-mail after you sent it to hundreds of people. - Jonathan M Davispeople make mistakes that can't be changed. 1) please dont write AI for people control system :) 2) too complicated. my suggestion (allow to edit post in next 5mins) is more humane.PS need to allow edit post for 5min at at leastOr you can: 1) Revise it better before posting. 2) If you use e-mail instead of WEB Front-End, some e-mail services and applications (Like Thunderbird) allows you to hold it for some time before sending.Many of us use the mailing list or newsgroup interfaces and have no interest in using the web interface. If the web interface can be improved in ways that work well with the newsgroup and the mailing list interfaces, then fine. Have at it. But editing messages really doesn't work well with that. And if you want to move away from the backend being a newsgroup with a mailing list as one of the interfaces, you're going to find a fair bit of opposition to that. - Jonathan M DavisAnd for D, the web interface is _not_ what controls the data. It's a client just like my e-mail client is and just like Walter's newsgroup client is. So, all it can edit is its local cache, which would make it out-of-sync with everyone else. Or it could send out a second message - which is exactly what you have to do right now. And because that's what you have to do, it doesn't give the false impression that you can edit previously sent messages. - Jonathan M DavisAnd? This is set in stone? There's no way to implement something better?
Jun 09 2019
On 09.06.19 20:52, Exil wrote:And? This is set in stone? There's no way to implement something better?Edit functionality is not "something better". It's perfectly fine that you can't retroactively change what you said in the past.
Jun 09 2019
On 6/9/19 1:09 PM, KnightMare wrote:On Sunday, 9 June 2019 at 16:45:18 UTC, 12345swordy wrote:Sadly it was meant as a generalized "is-a". Implementation botched that, I'm afraid, beyond repair. We'd be better off deprecating it and allowing some simple form of subtyping for structs.What is wrong with alias this?in my mind "alias this" is a crutch that allow to move on, that tries to replace "has-a" with "is-a" and at the same time introduces an implicit conversion operator.
Jun 09 2019
On Sunday, 9 June 2019 at 19:47:26 UTC, Andrei Alexandrescu wrote:Sadly it was meant as a generalized "is-a". Implementation botched that, I'm afraid, beyond repair. We'd be better off deprecating it and allowing some simple form of subtyping for structs.I like the `alias this` feature quite a lot, but it does have a kludgy feeling to it when you get some experience with it. For example, overload rules (or lack thereof). I don't think of it so much as an "is-a" relationship, but more as a kind of mixin (for lack of a better word) where you mix the public interface of an aggregate's field with the public interface of the aggregate itself. Though, now that I think of it, I wonder if that can be achieved with metaprogramming instead. In that case, I'd probably prefer the metaprogramming technique. I'm curious, though, so I welcome more elaboration on the shortcomings of the implementation. Mike
Jun 09 2019
On Monday, 10 June 2019 at 02:12:55 UTC, Mike Franklin wrote:For example, overload rules (or lack thereof).Sorry, I mean resolution rules.
Jun 09 2019
On 6/9/19 4:05 AM, Manu wrote:I am really really tired of this pattern: struct DerivedStruct { static if (BaseStruct.tupleof.length > 0) BaseStruct base; else ref inout(BaseStruct) base() inout { return *cast(inout(BaseStruct)*)&this; } alias base this; // derived members //... } Imagine if we could just write: struct DerivedStruct : BaseStruct { // derived members //... } Just imagine!Not necessarily objecting here, but does this pattern really come up all that often? I'm not even entirely sure what's going on in the "static else" there. Is it just saying: "If the BaseStruct is all methods and no data, then don't bother letting `BaseStruct base` add extra obviously-never-used bytes in DerivedStruct?" If so, it sounds like maybe that's an optimization the language/compiler could/should be doing (semi-?)automatically?
Jun 09 2019
On Sunday, 9 June 2019 at 19:04:50 UTC, Nick Sabalausky (Abscissa) wrote:I'm not even entirely sure what's going on in the "static else" there. Is it just saying: "If the BaseStruct is all methods and no data, then don't bother letting `BaseStruct base` add extra obviously-never-used bytes in DerivedStruct?" If so, it sounds like maybe that's an optimization the language/compiler could/should be doing (semi-?)automatically?Structs are always at least 1 byte in size, even when they contain no fields. This causes unnecessary bloat for reasons that I never understood.
Jun 09 2019
On 6/9/2019 12:40 PM, Vladimir Panteleev wrote:Structs are always at least 1 byte in size, even when they contain no fields. This causes unnecessary bloat for reasons that I never understood.The reason is so that each struct instance is at a unique address. There are some rules in C++ where sometimes a struct with no fields occupies 1 byte, sometimes 0 bytes. I don't recall what they are at the moment.
Jun 09 2019
On Monday, 10 June 2019 at 03:08:26 UTC, Walter Bright wrote:On 6/9/2019 12:40 PM, Vladimir Panteleev wrote:There is a (proposal?) for a no unique address attribute to disappear the address of structs the take up no room.Structs are always at least 1 byte in size, even when they contain no fields. This causes unnecessary bloat for reasons that I never understood.The reason is so that each struct instance is at a unique address. There are some rules in C++ where sometimes a struct with no fields occupies 1 byte, sometimes 0 bytes. I don't recall what they are at the moment.
Jun 09 2019
On Monday, 10 June 2019 at 04:03:38 UTC, Nicholas Wilson wrote:There is a (proposal?) for a no unique address attribute to disappear the address of structs the take up no room.Found it: https://en.cppreference.com/w/cpp/language/attributes/no_unique_address Looks like there are a bunch of weird edge cases with it though: struct Empty {}; struct Z { char c; [[no_unique_address]] Empty e1, e2; }; // e1 and e2 cannot share the same address because they have the // same type, even though they are marked with [[no_unique_address]]. // However, either may share address with c. static_assert(sizeof(Z) >= 2);
Jun 09 2019
On 6/9/2019 10:13 PM, Nicholas Wilson wrote:On Monday, 10 June 2019 at 04:03:38 UTC, Nicholas Wilson wrote:I didn't know about that attribute. Thanks for digging it up. Sheesh.There is a (proposal?) for a no unique address attribute to disappear the address of structs the take up no room.Found it: https://en.cppreference.com/w/cpp/language/attributes/no_unique_address Looks like there are a bunch of weird edge cases with it though: struct Empty {}; struct Z { char c; [[no_unique_address]] Empty e1, e2; }; // e1 and e2 cannot share the same address because they have the // same type, even though they are marked with [[no_unique_address]]. // However, either may share address with c. static_assert(sizeof(Z) >= 2);
Jun 10 2019
On Monday, 10 June 2019 at 09:35:25 UTC, Walter Bright wrote:I didn't know about that attribute. Thanks for digging it up.Np.Sheesh.Touché.
Jun 10 2019
On 6/10/19 12:03 AM, Nicholas Wilson wrote:On Monday, 10 June 2019 at 03:08:26 UTC, Walter Bright wrote:Would it really be a problem for the addresses of zero-byte structs to just simply be null?On 6/9/2019 12:40 PM, Vladimir Panteleev wrote:There is a (proposal?) for a no unique address attribute to disappear the address of structs the take up no room.Structs are always at least 1 byte in size, even when they contain no fields. This causes unnecessary bloat for reasons that I never understood.The reason is so that each struct instance is at a unique address. There are some rules in C++ where sometimes a struct with no fields occupies 1 byte, sometimes 0 bytes. I don't recall what they are at the moment.
Jun 10 2019
On Mon, Jun 10, 2019 at 06:35:16PM -0400, Nick Sabalausky (Abscissa) via Digitalmars-d wrote:On 6/10/19 12:03 AM, Nicholas Wilson wrote:Probably, if people expect: struct S {} S s; assert(&s !is null); to work. TBH, though, expecting different instances of a 0-sized struct to have distinct addresses is kind of a strange obscure case, and I'm not convinced it's worth the resulting slew of messy special cases just to cater to it. But that ship has long since sailed, and I'm not sure it's worth fighting over anymore. T -- Chance favours the prepared mind. -- Louis PasteurOn Monday, 10 June 2019 at 03:08:26 UTC, Walter Bright wrote:Would it really be a problem for the addresses of zero-byte structs to just simply be null?On 6/9/2019 12:40 PM, Vladimir Panteleev wrote:There is a (proposal?) for a no unique address attribute to disappear the address of structs the take up no room.Structs are always at least 1 byte in size, even when they contain no fields. This causes unnecessary bloat for reasons that I never understood.The reason is so that each struct instance is at a unique address. There are some rules in C++ where sometimes a struct with no fields occupies 1 byte, sometimes 0 bytes. I don't recall what they are at the moment.
Jun 10 2019
On 6/10/19 7:00 PM, H. S. Teoh wrote:On Mon, Jun 10, 2019 at 06:35:16PM -0400, Nick Sabalausky (Abscissa) via Digitalmars-d wrote:Ehh, maybe, but since when does anyone ever check a D struct's address for being null? Even if you DID have a struct who's address was null (due to being zero size), then unlike for classes, using the struct's methods or static members would still be no problem since it wouldn't involve dereferencing the null (Instead, for the static members it's irrelevent entirely, and for the rest: it would just simply pass null as the hidden argument to member functions which - outside of system pointer manipulation - would still have no way to actually dereference the null, because there's no non-static data members to even refer to, let alone access.) Or, heck, even just have it share an address with another data member. That or the null thing, I see no realistic problem either way. Or if you really want to be needlessly clumsy about it, have an attribute or pragma or something that says "If this field is a zero-byte struct, then for the love of god make it zero byte, I don't even care how you do it." I really don't like the whole "ships have sailed" theme in D though. It just gives a straight up middle finger to "The Last Thing D Needs" and to the whole reason for D's creation in the first place - to fix stupid legacy mistakes. And yea, sure, of course we have bigger fish to fry. But that should never be a reason to say "The mistake is realistically fixable, but NO, never gonna anyway!" instead of "Right, that was a mistake and it's fixable. We should fix it sooner or later BUT it's not a high priority right now."Would it really be a problem for the addresses of zero-byte structs to just simply be null?Probably, if people expect: struct S {} S s; assert(&s !is null); to work.
Jun 11 2019
On Wed, Jun 12, 2019 at 12:31:24AM -0400, Nick Sabalausky (Abscissa) via Digitalmars-d wrote:On 6/10/19 7:00 PM, H. S. Teoh wrote:I wouldn't say it occurs to structs specifically, but in generic code, it's conceivable you'd want to receive pointers and check whether they're actually pointing to something or if there's no value (e.g., using null as a kind of absence-of-data indicator). There might be unexpected interaction with code that uses null for indicating, e.g., whether a container slot exists, which becomes problematic if null is also the address of an instance of a 0-sized type (thereby conflating "non-existent slot" with "slot exists but data is 0 bytes). This is kinda contrived, though, and honestly I would vote for not supporting this sort of usage. But it's the kind of thing certain people might get up in arms about, if this behaviour were changed.On Mon, Jun 10, 2019 at 06:35:16PM -0400, Nick Sabalausky (Abscissa) via Digitalmars-d wrote:Ehh, maybe, but since when does anyone ever check a D struct's address for being null?Would it really be a problem for the addresses of zero-byte structs to just simply be null?Probably, if people expect: struct S {} S s; assert(&s !is null); to work.Or, heck, even just have it share an address with another data member. That or the null thing, I see no realistic problem either way. Or if you really want to be needlessly clumsy about it, have an attribute or pragma or something that says "If this field is a zero-byte struct, then for the love of god make it zero byte, I don't even care how you do it."Maybe just alias it to void[0], like somebody proposed?I really don't like the whole "ships have sailed" theme in D though. It just gives a straight up middle finger to "The Last Thing D Needs" and to the whole reason for D's creation in the first place - to fix stupid legacy mistakes.Personally, I agree that we shouldn't shy away from breaking changes if it improves the language for the long term. After all, that's what the deprecation process is for. But I'm not holding my breath for D leadership to buy into this sort of breaking change.And yea, sure, of course we have bigger fish to fry. But that should never be a reason to say "The mistake is realistically fixable, but NO, never gonna anyway!" instead of "Right, that was a mistake and it's fixable. We should fix it sooner or later BUT it's not a high priority right now."In fact, I agree. But I'm also not holding my breath for D leadership to change this attitude anytime soon. Cf. the bool fiasco, the char -> int implicit conversion (C promotion rules) fiasco, autodecoding (which is by now universally acknowledged as a mistake, but nobody has yet dared to take the first step to actually kill it), etc.. At some point, I seriously want to entertain the idea of D3. It used to be immediately shot down as not being likely, but with Andrei's recent change of stance about std.v2, there's a faint glimmer of hope that perhaps one day D3 could become reality. T -- Gone Chopin. Bach in a minuet.
Jun 11 2019
On Wednesday, 12 June 2019 at 06:00:12 UTC, H. S. Teoh wrote:This is kinda contrived, though, and honestly I would vote for not supporting this sort of usage. But it's the kind of thing certain people might get up in arms about, if this behaviour were changed.Since you'd still have to "alias this" the alias, it would probably cause more problem as it would now act as an array in some regard.Or, heck, even just have it share an address with another data member. That or the null thing, I see no realistic problem either way. Or if you really want to be needlessly clumsy about it, have an attribute or pragma or something that says "If this field is a zero-byte struct, then for the love of god make it zero byte, I don't even care how you do it."Maybe just alias it to void[0], like somebody proposed?Don't think it will. If D3 happens, then that means there will be D2 code that can't work with D3. Creating a std.v2 means that old code can just use the old version of the std and still work without having to rewrite their code. They can also use new D features while still using the old std library. One is a lot easier to deal with than the other.And yea, sure, of course we have bigger fish to fry. But that should never be a reason to say "The mistake is realistically fixable, but NO, never gonna anyway!" instead of "Right, that was a mistake and it's fixable. We should fix it sooner or later BUT it's not a high priority right now."In fact, I agree. But I'm also not holding my breath for D leadership to change this attitude anytime soon. Cf. the bool fiasco, the char -> int implicit conversion (C promotion rules) fiasco, autodecoding (which is by now universally acknowledged as a mistake, but nobody has yet dared to take the first step to actually kill it), etc.. At some point, I seriously want to entertain the idea of D3. It used to be immediately shot down as not being likely, but with Andrei's recent change of stance about std.v2, there's a faint glimmer of hope that perhaps one day D3 could become reality. T
Jun 12 2019
On Monday, June 10, 2019 5:00:40 PM MDT H. S. Teoh via Digitalmars-d wrote:On Mon, Jun 10, 2019 at 06:35:16PM -0400, Nick Sabalausky (Abscissa) viaDigitalmars-d wrote:There's also assert(&s); which calls the struct's invariant, though I doubt that many people know that, and unless someone is trying to do that in generic code or has an invariant which checks something other than the member variables' state, it wouldn't really matter if you couldn't do it with a struct with no member variables. - Jonathan M DavisOn 6/10/19 12:03 AM, Nicholas Wilson wrote:Probably, if people expect: struct S {} S s; assert(&s !is null); to work. TBH, though, expecting different instances of a 0-sized struct to have distinct addresses is kind of a strange obscure case, and I'm not convinced it's worth the resulting slew of messy special cases just to cater to it. But that ship has long since sailed, and I'm not sure it's worth fighting over anymore.On Monday, 10 June 2019 at 03:08:26 UTC, Walter Bright wrote:Would it really be a problem for the addresses of zero-byte structs to just simply be null?On 6/9/2019 12:40 PM, Vladimir Panteleev wrote:There is a (proposal?) for a no unique address attribute to disappear the address of structs the take up no room.Structs are always at least 1 byte in size, even when they contain no fields. This causes unnecessary bloat for reasons that I never understood.The reason is so that each struct instance is at a unique address. There are some rules in C++ where sometimes a struct with no fields occupies 1 byte, sometimes 0 bytes. I don't recall what they are at the moment.
Jun 10 2019
On Monday, 10 June 2019 at 03:08:26 UTC, Walter Bright wrote:There are some rules in C++ where sometimes a struct with no fields occupies 1 byte, sometimes 0 bytes. I don't recall what they are at the moment.Yes, empty base class optimization: https://en.cppreference.com/w/cpp/language/ebo
Jun 10 2019
On Monday, 10 June 2019 at 03:08:26 UTC, Walter Bright wrote:On 6/9/2019 12:40 PM, Vladimir Panteleev wrote:What advantages does this provide? Surely it can't be more important than being able to place behavior/policy in structs with no overhead?Structs are always at least 1 byte in size, even when they contain no fields. This causes unnecessary bloat for reasons that I never understood.The reason is so that each struct instance is at a unique address.
Jun 10 2019
On 6/10/2019 3:49 AM, Vladimir Panteleev wrote:On Monday, 10 June 2019 at 03:08:26 UTC, Walter Bright wrote:I don't remember all the rationale (30 years ago!), but a couple reasons are: 1. How would an array of 0 size elements work, when the pointer past the end is the same as the pointer to the start? 2. How would you determine the dimension of an array of 0 size elements? sizeof(Array)/sizeof(Array[0]) ? Oops!The reason is so that each struct instance is at a unique address.What advantages does this provide? Surely it can't be more important than being able to place behavior/policy in structs with no overhead?
Jun 10 2019
On Tuesday, 11 June 2019 at 06:29:58 UTC, Walter Bright wrote:1. How would an array of 0 size elements work, when the pointer past the end is the same as the pointer to the start? 2. How would you determine the dimension of an array of 0 size elements? sizeof(Array)/sizeof(Array[0]) ? Oops!But... 0-length arrays in D are already 0 bytes in size. struct S { int a; ubyte[0] b; int c; } pragma(msg, S.tupleof.offsetof); // tuple(0LU, 4LU, 4LU) pragma(msg, S.b.sizeof); // 0LU We actually take advantage of this by declaring hashsets as void[0][Key]. The same applies to two-dimensional 0-length arrays (T[0][0]), which would make them an array with 0-size elements. I don't think that's been a problem.
Jun 11 2019
On 11/06/2019 10:02 PM, Vladimir Panteleev wrote:We actually take advantage of this by declaring hashsets as void[0][Key].Oh that's a neat trick, I just use a bool!
Jun 11 2019
On 6/11/2019 3:02 AM, Vladimir Panteleev wrote:[...]Ok, you got me there. Here's what Stroustrup says: http://www.stroustrup.com/bs_faq2.html#sizeof-empty
Jun 12 2019
On Thursday, 13 June 2019 at 05:31:23 UTC, Walter Bright wrote:On 6/11/2019 3:02 AM, Vladimir Panteleev wrote:From the page: Empty a, b; if (&a == &b) cout << "impossible: report error to compiler supplier"; However, no further justification is provided why that is a problem. Perhaps it's something the C++ spec was written to guarantee, but does not apply to D?[...]Ok, you got me there. Here's what Stroustrup says: http://www.stroustrup.com/bs_faq2.html#sizeof-empty
Jun 13 2019
On Thursday, 13 June 2019 at 09:44:12 UTC, Vladimir Panteleev wrote:On Thursday, 13 June 2019 at 05:31:23 UTC, Walter Bright wrote:Just for amusement, rust has ZSTs (zero sized types) and Empty types (they distinguish between the two) - https://doc.rust-lang.org/nomicon/exotic-sizes.html#zero-sized-types-zsts And here's a consequence of that: https://github.com/rust-lang/rust/blob/e011fe1c132010e261cc9ea658da73152f1f7fc7/src/liballoc/vec.rs#L2428 Here's a more detailed "beware of these guys" https://gankro.github.io/blah/only-in-rust/#honorable-mention-zero-sized-types-zsts "However, in low level (unsafe) code zero-sized types can be a bit hazardous, for two reasons: If you try to malloc some number of zero-sized types naively, you'll pass an allocation size of 0 to the allocator, which is implementation-defined at best. Also you want to avoid allocating these things anyway! If you try to offset a pointer to a zero-sized type naively, you will get nowhere. This breaks a C-style "two pointers moving towards each other" iterator." Swift and go are also mentioned in the above link. Cheers, - AliOn 6/11/2019 3:02 AM, Vladimir Panteleev wrote:From the page: Empty a, b; if (&a == &b) cout << "impossible: report error to compiler supplier"; However, no further justification is provided why that is a problem. Perhaps it's something the C++ spec was written to guarantee, but does not apply to D?[...]Ok, you got me there. Here's what Stroustrup says: http://www.stroustrup.com/bs_faq2.html#sizeof-empty
Jun 13 2019
On Thursday, 13 June 2019 at 10:25:02 UTC, aliak wrote:If you try to malloc some number of zero-sized types naively, you'll pass an allocation size of 0 to the allocator, which is implementation-defined at best. Also you want to avoid allocating these things anyway!On 64 bit architectures you probably could write a custom malloc that will return a unique address outside the memory map for 0-sized allocations. It would have to mark it in a bitmap so that it could be freed. *shrugs* But, I doubt that people actually do this often. Allocating 4-8 bytes probably would be ok, so you could just redefine malloc as malloc(max(allocationsize,8)).
Jun 13 2019
On Thursday, 13 June 2019 at 10:25:02 UTC, aliak wrote:Here's a more detailed "beware of these guys" https://gankro.github.io/blah/only-in-rust/#honorable-mention-zero-sized-types-zsts "However, in low level (unsafe) code zero-sized types can be a bit hazardous, for two reasons: If you try to malloc some number of zero-sized types naively, you'll pass an allocation size of 0 to the allocator, which is implementation-defined at best. Also you want to avoid allocating these things anyway!Especially if you use C allocation realloc() as calling it with size 0 is synonymous to free(). Ouch!
Jun 13 2019
On Thursday, 13 June 2019 at 12:20:14 UTC, Patrick Schluter wrote:When would that be a problem? Any pointer is a valid pointer for a zero-sized object, as it can never be meaningfully "dereferenced" (never minding only pretending to do that for purposes of metaprogramming and such).If you try to malloc some number of zero-sized types naively, you'll pass an allocation size of 0 to the allocator, which is implementation-defined at best. Also you want to avoid allocating these things anyway!Especially if you use C allocation realloc() as calling it with size 0 is synonymous to free(). Ouch!
Jun 15 2019
On Saturday, 15 June 2019 at 10:19:25 UTC, Vladimir Panteleev wrote:On Thursday, 13 June 2019 at 12:20:14 UTC, Patrick Schluter wrote:Oh, I guess it would be an issue if you tried to grow it back to non-zero size.Especially if you use C allocation realloc() as calling it with size 0 is synonymous to free(). Ouch!When would that be a problem? Any pointer is a valid pointer for a zero-sized object, as it can never be meaningfully "dereferenced" (never minding only pretending to do that for purposes of metaprogramming and such).
Jun 15 2019
On 6/11/19 2:29 AM, Walter Bright wrote:2. How would you determine the dimension of an array of 0 size elements?By reading .length instead of performing an unnecessary division.
Jun 11 2019
On Wed, Jun 12, 2019 at 12:44:08AM -0400, Nick Sabalausky (Abscissa) via Digitalmars-d wrote:On 6/11/19 2:29 AM, Walter Bright wrote:+1. I never liked that nonsensical sizeof(array)/sizeof(array[0]) "trick" or idiom. It was a hack around a deficient language way back when. Today we have D, and D has .length. We should be using that instead. Why are we still bending over backwards to support outdated hacks? T -- Freedom of speech: the whole world has no right *not* to hear my spouting off!2. How would you determine the dimension of an array of 0 size elements?By reading .length instead of performing an unnecessary division.
Jun 11 2019
On 6/9/2019 1:05 AM, Manu wrote:I am really really tired of this pattern:Is your real complaint this: --- #include <stdio.h> struct B { }; struct S : B { char c; }; struct T { B b; char c; }; void main(){ printf("%d %d\n", sizeof(struct S), sizeof(struct T)); } --- which prints: 1 2 ?
Jun 09 2019
On Sun, Jun 9, 2019 at 9:50 PM Walter Bright via Digitalmars-d <digitalmars-d puremagic.com> wrote:On 6/9/2019 1:05 AM, Manu wrote:That is indeed the feature that necessitates my 'solution', but `alias this` is generally undesirable in this pattern in its own right, for some of the reasons I listed. `alias this` does not feel satisfying in this context in its own right. Also, if this hack takes the alias this slot, then it can't be used for what it's usually used for (enabling implicit conversion) and sometimes needs conflict.I am really really tired of this pattern:Is your real complaint this: --- #include <stdio.h> struct B { }; struct S : B { char c; }; struct T { B b; char c; }; void main(){ printf("%d %d\n", sizeof(struct S), sizeof(struct T)); } --- which prints: 1 2 ?
Jun 09 2019
On 6/9/2019 10:52 PM, Manu wrote:On Sun, Jun 9, 2019 at 9:50 PM Walter Bright via Digitalmars-d <digitalmars-d puremagic.com> wrote:I don't see where you listed reasons? Other than it just being unsightly?On 6/9/2019 1:05 AM, Manu wrote:That is indeed the feature that necessitates my 'solution', but `alias this` is generally undesirable in this pattern in its own right, for some of the reasons I listed.I am really really tired of this pattern:Is your real complaint this: --- #include <stdio.h> struct B { }; struct S : B { char c; }; struct T { B b; char c; }; void main(){ printf("%d %d\n", sizeof(struct S), sizeof(struct T)); } --- which prints: 1 2 ?`alias this` does not feel satisfying in this context in its own right. Also, if this hack takes the alias this slot, then it can't be used for what it's usually used for (enabling implicit conversion) and sometimes needs conflict.Are you using 'alias this' to try to do multiple inheritance? Please don't :-(
Jun 10 2019
On Mon, Jun 10, 2019 at 2:40 AM Walter Bright via Digitalmars-d <digitalmars-d puremagic.com> wrote:On 6/9/2019 10:52 PM, Manu wrote:Somehow this thread forked from my OP, I listed reasons in my second post there, mostly relating to editor and debug experience. This pattern I illustrate has a tendency to obscure code and intent not just to human readers, but also to the IDE tooling. Syntax highlighting fails, auto-completion fails, debuginfo does not understand the hack and presents incorrectly, etc.On Sun, Jun 9, 2019 at 9:50 PM Walter Bright via Digitalmars-d <digitalmars-d puremagic.com> wrote:I don't see where you listed reasons? Other than it just being unsightly?On 6/9/2019 1:05 AM, Manu wrote:That is indeed the feature that necessitates my 'solution', but `alias this` is generally undesirable in this pattern in its own right, for some of the reasons I listed.I am really really tired of this pattern:Is your real complaint this: --- #include <stdio.h> struct B { }; struct S : B { char c; }; struct T { B b; char c; }; void main(){ printf("%d %d\n", sizeof(struct S), sizeof(struct T)); } --- which prints: 1 2 ?No, I usually use alias this for implicit conversion... which is a pattern I would be overjoyed to abandon if we had some way to mark constructors or cast operators as implicit! I also use alias this to fake struct inheritance. I'd argue that I shouldn't be using alias this for either of these reasons. They're both ugly hacks in the face of language deficiency which really subvert the intent of the code, and ruin the editor/debug experience.`alias this` does not feel satisfying in this context in its own right. Also, if this hack takes the alias this slot, then it can't be used for what it's usually used for (enabling implicit conversion) and sometimes needs conflict.Are you using 'alias this' to try to do multiple inheritance? Please don't :-(
Jun 10 2019
On 6/9/2019 10:52 PM, Manu wrote:That is indeed the feature that necessitates my 'solution'One possibility is that if the alias this is referring to a struct with no fields, it gets a 0 size. This will mimic the behavior of C++.
Jun 10 2019
On Mon, Jun 10, 2019 at 2:55 AM Walter Bright via Digitalmars-d <digitalmars-d puremagic.com> wrote:On 6/9/2019 10:52 PM, Manu wrote:The struct exists as a member irrespective of the alias this. And at this point, you have implemented struct inheritance in absolute terms, but why would you prefer an ugly and unclear syntax to specify it? Inheritance syntax is blindingly obvious and easy to see, base-struct + alias this is awkward to spot; the base member could be anywhere, and the `alias this` may or may not be present (you have to go looking for it), and the line may not even be nearby...That is indeed the feature that necessitates my 'solution'One possibility is that if the alias this is referring to a struct with no fields, it gets a 0 size. This will mimic the behavior of C++.
Jun 10 2019
On 6/9/2019 10:52 PM, Manu wrote:That is indeed the feature that necessitates my 'solution',Is it specifically for C++ interop, or you just want the zero size?
Jun 10 2019
On Mon, Jun 10, 2019 at 11:30 PM Walter Bright via Digitalmars-d <digitalmars-d puremagic.com> wrote:On 6/9/2019 10:52 PM, Manu wrote:It occurs frequently in C++ interop, but that's only because most of my code exists in C++. I do, and will continue to use base structs in C++ and in D for exactly the same reasons. Every codebase I have ever worked in uses base struct's to DRY liberally, thousands of engineers think this is fine, and I've never heard anyone think it's unusual, or weird/problematic.That is indeed the feature that necessitates my 'solution',Is it specifically for C++ interop,or you just want the zero size?A zero size solution removes the static if hack, but it doesn't remove the alias this hack. I want to remove both hacks. I can't stress enough that struct inheritance exists, it's extremely common, and we will continue to do it as a completely normal practice with no apology. Please don't make our code ugly and unnecessarily difficult to understand for no reason. If you fear misunderstanding with polymorphism, fear not; this is not C++, struct is strictly a value type, there is no vtable, no virtual, no override, etc... there would be compile errors at every turn if anyone ever confused struct inheritance for polymorphism. We have a HUGE advantage here...
Jun 11 2019
On 6/11/2019 12:06 AM, Manu wrote:On Mon, Jun 10, 2019 at 11:30 PM Walter Bright via Digitalmars-d <digitalmars-d puremagic.com> wrote:Can I ask again, in a different way, why do you need the 0 size?On 6/9/2019 10:52 PM, Manu wrote:It occurs frequently in C++ interop, but that's only because most of my code exists in C++. I do, and will continue to use base structs in C++ and in D for exactly the same reasons. Every codebase I have ever worked in uses base struct's to DRY liberally, thousands of engineers think this is fine, and I've never heard anyone think it's unusual, or weird/problematic.That is indeed the feature that necessitates my 'solution',Is it specifically for C++ interop,or you just want the zero size?A zero size solution removes the static if hack, but it doesn't remove the alias this hack. I want to remove both hacks. I can't stress enough that struct inheritance exists, it's extremely common, and we will continue to do it as a completely normal practice with no apology. Please don't make our code ugly and unnecessarily difficult to understand for no reason. If you fear misunderstanding with polymorphism, fear not; this is not C++, struct is strictly a value type, there is no vtable, no virtual, no override, etc... there would be compile errors at every turn if anyone ever confused struct inheritance for polymorphism. We have a HUGE advantage here...
Jun 11 2019
On Tue, Jun 11, 2019 at 1:00 AM Walter Bright via Digitalmars-d <digitalmars-d puremagic.com> wrote:On 6/11/2019 12:06 AM, Manu wrote:To handle base structs with no members.On Mon, Jun 10, 2019 at 11:30 PM Walter Bright via Digitalmars-d <digitalmars-d puremagic.com> wrote:Can I ask again, in a different way, why do you need the 0 size?On 6/9/2019 10:52 PM, Manu wrote:It occurs frequently in C++ interop, but that's only because most of my code exists in C++. I do, and will continue to use base structs in C++ and in D for exactly the same reasons. Every codebase I have ever worked in uses base struct's to DRY liberally, thousands of engineers think this is fine, and I've never heard anyone think it's unusual, or weird/problematic.That is indeed the feature that necessitates my 'solution',Is it specifically for C++ interop,or you just want the zero size?A zero size solution removes the static if hack, but it doesn't remove the alias this hack. I want to remove both hacks. I can't stress enough that struct inheritance exists, it's extremely common, and we will continue to do it as a completely normal practice with no apology. Please don't make our code ugly and unnecessarily difficult to understand for no reason. If you fear misunderstanding with polymorphism, fear not; this is not C++, struct is strictly a value type, there is no vtable, no virtual, no override, etc... there would be compile errors at every turn if anyone ever confused struct inheritance for polymorphism. We have a HUGE advantage here...
Jun 11 2019
On Tuesday, 11 June 2019 at 18:19:05 UTC, Manu wrote:On Tue, Jun 11, 2019 at 1:00 AM Walter Bright via Digitalmars-d <digitalmars-d puremagic.com> wrote:Kind of curious, what do you use a base class for that has no members, is a size of zero, and also has no vtable or virtual functions?On 6/11/2019 12:06 AM, Manu wrote:To handle base structs with no members.On Mon, Jun 10, 2019 at 11:30 PM Walter Bright via Digitalmars-d <digitalmars-d puremagic.com> wrote:Can I ask again, in a different way, why do you need the 0 size?On 6/9/2019 10:52 PM, Manu wrote:It occurs frequently in C++ interop, but that's only because most of my code exists in C++. I do, and will continue to use base structs in C++ and in D for exactly the same reasons. Every codebase I have ever worked in uses base struct's to DRY liberally, thousands of engineers think this is fine, and I've never heard anyone think it's unusual, or weird/problematic.That is indeed the feature that necessitates my 'solution',Is it specifically for C++ interop,or you just want the zero size?A zero size solution removes the static if hack, but it doesn't remove the alias this hack. I want to remove both hacks. I can't stress enough that struct inheritance exists, it's extremely common, and we will continue to do it as a completely normal practice with no apology. Please don't make our code ugly and unnecessarily difficult to understand for no reason. If you fear misunderstanding with polymorphism, fear not; this is not C++, struct is strictly a value type, there is no vtable, no virtual, no override, etc... there would be compile errors at every turn if anyone ever confused struct inheritance for polymorphism. We have a HUGE advantage here...
Jun 11 2019
On Tue, Jun 11, 2019 at 12:35 PM Exil via Digitalmars-d <digitalmars-d puremagic.com> wrote:On Tuesday, 11 June 2019 at 18:19:05 UTC, Manu wrote:Metaprogramming; it's a template argument. It might be the case that some method is expected to exist, but the particular implementation may or may not require any data. Virtuals are dead man, nobody uses OOP anymore. It's all about contracts and things like that. Base classes might be expected to have a method, and there may be a static assert to prove that some API is satisfied, but the implementation may want to have some additional state. This pattern doesn't exclusively apply to inheritance, but that's the case on trial.On Tue, Jun 11, 2019 at 1:00 AM Walter Bright via Digitalmars-d <digitalmars-d puremagic.com> wrote:Kind of curious, what do you use a base class for that has no members, is a size of zero, and also has no vtable or virtual functions?On 6/11/2019 12:06 AM, Manu wrote:To handle base structs with no members.On Mon, Jun 10, 2019 at 11:30 PM Walter Bright via Digitalmars-d <digitalmars-d puremagic.com> wrote:Can I ask again, in a different way, why do you need the 0 size?On 6/9/2019 10:52 PM, Manu wrote:It occurs frequently in C++ interop, but that's only because most of my code exists in C++. I do, and will continue to use base structs in C++ and in D for exactly the same reasons. Every codebase I have ever worked in uses base struct's to DRY liberally, thousands of engineers think this is fine, and I've never heard anyone think it's unusual, or weird/problematic.That is indeed the feature that necessitates my 'solution',Is it specifically for C++ interop,or you just want the zero size?A zero size solution removes the static if hack, but it doesn't remove the alias this hack. I want to remove both hacks. I can't stress enough that struct inheritance exists, it's extremely common, and we will continue to do it as a completely normal practice with no apology. Please don't make our code ugly and unnecessarily difficult to understand for no reason. If you fear misunderstanding with polymorphism, fear not; this is not C++, struct is strictly a value type, there is no vtable, no virtual, no override, etc... there would be compile errors at every turn if anyone ever confused struct inheritance for polymorphism. We have a HUGE advantage here...
Jun 11 2019
On 6/11/19 7:45 PM, Manu wrote:On Tue, Jun 11, 2019 at 12:35 PM Exil via Digitalmars-d <digitalmars-d puremagic.com> wrote:Subtyping is not needed for metaprogramming. (C++'s awkward way of doing it overuses it.)Kind of curious, what do you use a base class for that has no members, is a size of zero, and also has no vtable or virtual functions?Metaprogramming; it's a template argument.
Jun 12 2019
On Wed, Jun 12, 2019 at 11:40 PM Andrei Alexandrescu via Digitalmars-d <digitalmars-d puremagic.com> wrote:On 6/11/19 7:45 PM, Manu wrote:Overuse of `alias this` is not any better. `alias this` is relatively much more awkward, and I would say objectively less easy to read and understand. You can't miss the base at the top of the struct, you know exactly where to look for it. With `alias this`, you have to scan the object from top to bottom to see if it's there, and then you have to take note what object is acting as the base and look for that and where it sits relative to other members, and then worry about the zero-size hack. That alone makes C++'s "awkward way of doing it" look golden, but then there's also the issues with the IDE tooling, and that there's only one `alias this` slot, which we might need for implicit conversion of some sort. What's so upsetting about C++'s approach? You say 'subtyping', but that sounds like you're talking about polymorphism again. Perhaps it would be better to say 'extending', which is really what it is applied to a struct. I think it's a simple and natural syntax to do a simple and natural operation like extending a struct. Look, I'm not actually married to C++'s approach (if you have a better idea), but I'm dreadfully bored of D's shitty approach, I've had a decade to try and think it's cool, but I actually think it's more shit than I thought it was 10 years ago. I used to think it was a cool idea; it's a 'cute' use of a novel feature in D which achieves a goal... and like, bugger C++ and it's stupid face, and anything that's not like C++ is cool, but I was wrong. It's a shitty thing to write over and over again and I hate it, having done it **A LOT**. I haven't generally made a fuss about this like other things because it's not a blocker in any way, but it's important to express how bored I am of the pattern. It's not better.On Tue, Jun 11, 2019 at 12:35 PM Exil via Digitalmars-d <digitalmars-d puremagic.com> wrote:Subtyping is not needed for metaprogramming. (C++'s awkward way of doing it overuses it.)Kind of curious, what do you use a base class for that has no members, is a size of zero, and also has no vtable or virtual functions?Metaprogramming; it's a template argument.
Jun 13 2019
On Thursday, 13 June 2019 at 07:04:06 UTC, Manu wrote:On Wed, Jun 12, 2019 at 11:40 PM Andrei Alexandrescu via Digitalmars-d <digitalmars-d puremagic.com> wrote:Wouldn't it be better to allow structs to implement static only interfaces? -AlexOn 6/11/19 7:45 PM, Manu wrote:Overuse of `alias this` is not any better. `alias this` is relatively much more awkward, and I would say objectively less easy to read and understand. You can't miss the base at the top of the struct, you know exactly where to look for it. With `alias this`, you have to scan the object from top to bottom to see if it's there, and then you have to take note what object is acting as the base and look for that and where it sits relative to other members, and then worry about the zero-size hack. That alone makes C++'s "awkward way of doing it" look golden, but then there's also the issues with the IDE tooling, and that there's only one `alias this` slot, which we might need for implicit conversion of some sort. What's so upsetting about C++'s approach? You say 'subtyping', but that sounds like you're talking about polymorphism again. Perhaps it would be better to say 'extending', which is really what it is applied to a struct. I think it's a simple and natural syntax to do a simple and natural operation like extending a struct. Look, I'm not actually married to C++'s approach (if you have a better idea), but I'm dreadfully bored of D's shitty approach, I've had a decade to try and think it's cool, but I actually think it's more shit than I thought it was 10 years ago. I used to think it was a cool idea; it's a 'cute' use of a novel feature in D which achieves a goal... and like, bugger C++ and it's stupid face, and anything that's not like C++ is cool, but I was wrong. It's a shitty thing to write over and over again and I hate it, having done it **A LOT**. I haven't generally made a fuss about this like other things because it's not a blocker in any way, but it's important to express how bored I am of the pattern. It's not better.On Tue, Jun 11, 2019 at 12:35 PM Exil via Digitalmars-d <digitalmars-d puremagic.com> wrote:Subtyping is not needed for metaprogramming. (C++'s awkward way of doing it overuses it.)Kind of curious, what do you use a base class for that has no members, is a size of zero, and also has no vtable or virtual functions?Metaprogramming; it's a template argument.
Jun 13 2019
On Thu, Jun 13, 2019 at 7:55 AM 12345swordy via Digitalmars-d <digitalmars-d puremagic.com> wrote:I don't know what that means? Like D `interface`, which is a pure vtable with no data members? That's the opposite of what I want... what is a 'static' interface?[...] It's not better.Wouldn't it be better to allow structs to implement static only interfaces?
Jun 13 2019
On Thursday, 13 June 2019 at 22:12:37 UTC, Manu wrote:On Thu, Jun 13, 2019 at 7:55 AM 12345swordy via Digitalmars-d <digitalmars-d puremagic.com> wrote:Interface with only static functions and data members. No virtual function what so ever.I don't know what that means? Like D `interface`, which is a pure vtable with no data members? That's the opposite of what I want... what is a 'static' interface?[...] It's not better.Wouldn't it be better to allow structs to implement static only interfaces?
Jun 13 2019
On Thu, Jun 13, 2019 at 4:05 PM 12345swordy via Digitalmars-d <digitalmars-d puremagic.com> wrote:On Thursday, 13 June 2019 at 22:12:37 UTC, Manu wrote:Well... right. We're talking about struct's here. struct's don't have virtual functions.On Thu, Jun 13, 2019 at 7:55 AM 12345swordy via Digitalmars-d <digitalmars-d puremagic.com> wrote:Interface with only static functions and data members. No virtual function what so ever.I don't know what that means? Like D `interface`, which is a pure vtable with no data members? That's the opposite of what I want... what is a 'static' interface?[...] It's not better.Wouldn't it be better to allow structs to implement static only interfaces?
Jun 13 2019
On Thursday, 13 June 2019 at 23:28:37 UTC, Manu wrote:On Thu, Jun 13, 2019 at 4:05 PM 12345swordy via Digitalmars-d <digitalmars-d puremagic.com> wrote:I am saying that structs should be allow to inherent interfaces, provided that said interface only contains statics functions(with or without implementation) or data members. What you want is the ability to define a contract for the structs to inherited without any virtual functions.On Thursday, 13 June 2019 at 22:12:37 UTC, Manu wrote:Well... right. We're talking about struct's here. struct's don't have virtual functions.On Thu, Jun 13, 2019 at 7:55 AM 12345swordy via Digitalmars-d <digitalmars-d puremagic.com> wrote:Interface with only static functions and data members. No virtual function what so ever.I don't know what that means? Like D `interface`, which is a pure vtable with no data members? That's the opposite of what I want... what is a 'static' interface?[...] It's not better.Wouldn't it be better to allow structs to implement static only interfaces?
Jun 13 2019
On Thu, Jun 13, 2019 at 6:13 PM 12345swordy via Digitalmars-d <digitalmars-d puremagic.com> wrote:On Thursday, 13 June 2019 at 23:28:37 UTC, Manu wrote:I think that's much more weird than struct's inheriting a struct... an interface is everything other than a static non-virtual type... a struct is *exactly* that.On Thu, Jun 13, 2019 at 4:05 PM 12345swordy via Digitalmars-d <digitalmars-d puremagic.com> wrote:I am saying that structs should be allow to inherent interfaces, provided that said interface only contains statics functions(with or without implementation) or data members.On Thursday, 13 June 2019 at 22:12:37 UTC, Manu wrote:Well... right. We're talking about struct's here. struct's don't have virtual functions.On Thu, Jun 13, 2019 at 7:55 AM 12345swordy via Digitalmars-d <digitalmars-d puremagic.com> wrote:Interface with only static functions and data members. No virtual function what so ever.I don't know what that means? Like D `interface`, which is a pure vtable with no data members? That's the opposite of what I want... what is a 'static' interface?[...] It's not better.Wouldn't it be better to allow structs to implement static only interfaces?What you want is the ability to define a contract for the structs to inherited without any virtual functions.I would expect something different from a "contract"; that sounds like some expectations without some concrete details defined. And again, this is the opposite of that.
Jun 13 2019
On Thursday, 13 June 2019 at 22:12:37 UTC, Manu wrote:what is a 'static' interface?I would define it as something like this: static interface Processor { // Required methods for a struct void prepare(Options opts); void process(ubyte[] data); bool isReady(); Result get(); int integer; // No size, just a requirement } struct IncorrectProcessor : Processor { void prepare(Options opts) { ... } void doSomething() { ... } } // Implements all that's in the 'static interface' even the (public) data. struct CorrectProcessor : Processor { void prepare(Options opts) { ... } void process(ubyte[] data) { ... } bool isReady() { ... } Result get() { ... } int integer; void doSomething2() { ... } void doSomething3() { ... } } void myProcessorUseCase(Processor p) { p.prepare(opts); p.process(data); while(!p.isReady()) { ... } return p.get(); } // You can now call myProcessorUseCase with different types of processors with in different parts of code. No runtime type switching, no virtuals. myProcessorUseCase( incorrectProcessor ); // Error: 'incorrectProcessor' doesn't implement static interface 'Processor' correctly myProcessorUseCase( correctProcessor ); // OK ----- Basically, a static compile-time check that struct is of specific form. Kind of like compiling a different .c file for a shared/interface .h file for different builds, except not restricted to files and builds. No virtuals or anything. Compiling doesn't produce any artifacts just does the check. I've often wished for a feature like this. I suppose you can do template constraints, static ifs and meta, but honestly I find the result cumbersome and not very readable/debuggable.
Jun 14 2019
On 6/11/2019 11:19 AM, Manu wrote:For the 3rd time, why do you need it to have 0 size? I don't know what you mean by "handling" it.Can I ask again, in a different way, why do you need the 0 size?To handle base structs with no members.
Jun 12 2019
On Wed, Jun 12, 2019 at 10:25 PM Walter Bright via Digitalmars-d <digitalmars-d puremagic.com> wrote:On 6/11/2019 11:19 AM, Manu wrote:I hate wasting 8 bytes needlessly. Almost every struct I write is carefully packed and aligned to 16, 32, or 64 bytes and allocated in pools... that's 50%, 25%, or 12.5% memory wastage. There's also ABI compatibility with existing C++ where this is super-common. Consider that user-supplied <Allocator> is a base of every STL container, that's one case where I've had to deploy the static if hack a lot. Those are absolutely not polymorphic types, and you couldn't make that mistake no matter how hard you squinted. They sometimes use a helper called a 'packed pair' in the STL, which is like std::pair (obviously another not-a-polymorphic-type), but where one or the other element can be zero-sized and not waste memory. It's an aggregation tool.For the 3rd time, why do you need it to have 0 size? I don't know what you mean by "handling" it.Can I ask again, in a different way, why do you need the 0 size?To handle base structs with no members.
Jun 12 2019
On 6/12/2019 11:29 PM, Manu wrote:On Wed, Jun 12, 2019 at 10:25 PM Walter Bright via Digitalmars-d <digitalmars-d puremagic.com> wrote:Have you considered using template mixins? Since you're using a base struct merely as a namespace for some functions, that should work.On 6/11/2019 11:19 AM, Manu wrote:I hate wasting 8 bytes needlessly. Almost every struct I write is carefully packed and aligned to 16, 32, or 64 bytes and allocated in pools... that's 50%, 25%, or 12.5% memory wastage. There's also ABI compatibility with existing C++ where this is super-common. Consider that user-supplied <Allocator> is a base of every STL container, that's one case where I've had to deploy the static if hack a lot. Those are absolutely not polymorphic types, and you couldn't make that mistake no matter how hard you squinted. They sometimes use a helper called a 'packed pair' in the STL, which is like std::pair (obviously another not-a-polymorphic-type), but where one or the other element can be zero-sized and not waste memory. It's an aggregation tool.For the 3rd time, why do you need it to have 0 size? I don't know what you mean by "handling" it.Can I ask again, in a different way, why do you need the 0 size?To handle base structs with no members.
Jun 18 2019
On Tuesday, 18 June 2019 at 09:15:42 UTC, Walter Bright wrote:On 6/12/2019 11:29 PM, Manu wrote:The ABI compatibility point really needs to be reiterated here. If the end goal, especially with things like D++, is to drive adoption of D by ensuring C++ interop is simple then that's now going to result in a static analysis tool to look at any given C++ struct and work out whether it should or shouldn't be converted to a mixin template. And introduce the dissonance of a C++ type not actually being a type in D.There's also ABI compatibility with existing C++ where this is super-common. Consider that user-supplied <Allocator> is a base of every STL container, that's one case where I've had to deploy the static if hack a lot.Have you considered using template mixins? Since you're using a base struct merely as a namespace for some functions, that should work.
Jun 18 2019
On 6/18/2019 3:34 AM, Ethan wrote:You can do this: mixin template BaseMembers() { void memberFunction() { ... } } struct Base { mixin BaseMembers!(); } struct Derived { mixin BaseMembers!(); // walla! zero size for "inheritance"! Base b; // when I want C++ 1 byte size } It's not a thing of beauty, but nothing connected with C++ is :-)Have you considered using template mixins? Since you're using a base struct merely as a namespace for some functions, that should work.The ABI compatibility point really needs to be reiterated here. If the end goal, especially with things like D++, is to drive adoption of D by ensuring C++ interop is simple then that's now going to result in a static analysis tool to look at any given C++ struct and work out whether it should or shouldn't be converted to a mixin template. And introduce the dissonance of a C++ type not actually being a type in D.
Jun 18 2019
On 18.06.19 21:58, Walter Bright wrote:On 6/18/2019 3:34 AM, Ethan wrote:This works if Base and Derived are defined in the same module. Otherwise this does not do the correct thing, because mixin templates are analyzed in the scope into which they are mixed.You can do this: mixin template BaseMembers() { void memberFunction() { ... } } struct Base { mixin BaseMembers!(); } struct Derived { mixin BaseMembers!(); // walla! zero size for "inheritance"! Base b; // when I want C++ 1 byte size } It's not a thing of beauty, but nothing connected with C++ is :-)Have you considered using template mixins? Since you're using a base struct merely as a namespace for some functions, that should work.The ABI compatibility point really needs to be reiterated here. If the end goal, especially with things like D++, is to drive adoption of D by ensuring C++ interop is simple then that's now going to result in a static analysis tool to look at any given C++ struct and work out whether it should or shouldn't be converted to a mixin template. And introduce the dissonance of a C++ type not actually being a type in D.
Jun 18 2019
On 6/18/2019 5:01 PM, Timon Gehr wrote:This works if Base and Derived are defined in the same module. Otherwise this does not do the correct thing, because mixin templates are analyzed in the scope into which they are mixed.That is correct, but with some care you can make it work, even if the mixin template functions just forward to other functions which are evaluated in the BaseMembers' scope.
Jun 18 2019
On Wed, Jun 19, 2019 at 10:45 AM Walter Bright via Digitalmars-d <digitalmars-d puremagic.com> wrote:On 6/18/2019 5:01 PM, Timon Gehr wrote:I already have workarounds. That's not what this thread is about.This works if Base and Derived are defined in the same module. Otherwise this does not do the correct thing, because mixin templates are analyzed in the scope into which they are mixed.That is correct, but with some care you can make it work, even if the mixin template functions just forward to other functions which are evaluated in the BaseMembers' scope.
Jun 18 2019
On Wednesday, 19 June 2019 at 01:10:56 UTC, Manu wrote:On Wed, Jun 19, 2019 at 10:45 AM Walter Bright via Digitalmars-d <digitalmars-d puremagic.com> wrote:Not just my opinion, but what I perceive to be expected procedure here: The merits of any new feature have to be argued in terms of net benefit over existing solutions. Just my opinion: The best feature design often comes from struggling with current features. You obviously have done a lot of the second, but it seems that you think "it's obviously better, the current solutions are just ugly hacks, everyone will laugh at us" is going to convince people enough w.r.t. the former. Obvious hyperbole is obvious, but hopefully you get my point?On 6/18/2019 5:01 PM, Timon Gehr wrote:I already have workarounds. That's not what this thread is about.This works if Base and Derived are defined in the same module. Otherwise this does not do the correct thing, because mixin templates are analyzed in the scope into which they are mixed.That is correct, but with some care you can make it work, even if the mixin template functions just forward to other functions which are evaluated in the BaseMembers' scope.
Jun 25 2019
On Tue, Jun 18, 2019 at 7:20 PM Walter Bright via Digitalmars-d <digitalmars-d puremagic.com> wrote:On 6/12/2019 11:29 PM, Manu wrote:I mean, I love macro's as much as the next guy, and they're not at all embarrassing.On Wed, Jun 12, 2019 at 10:25 PM Walter Bright via Digitalmars-d <digitalmars-d puremagic.com> wrote:Have you considered using template mixins? Since you're using a base struct merely as a namespace for some functions, that should work.On 6/11/2019 11:19 AM, Manu wrote:I hate wasting 8 bytes needlessly. Almost every struct I write is carefully packed and aligned to 16, 32, or 64 bytes and allocated in pools... that's 50%, 25%, or 12.5% memory wastage. There's also ABI compatibility with existing C++ where this is super-common. Consider that user-supplied <Allocator> is a base of every STL container, that's one case where I've had to deploy the static if hack a lot. Those are absolutely not polymorphic types, and you couldn't make that mistake no matter how hard you squinted. They sometimes use a helper called a 'packed pair' in the STL, which is like std::pair (obviously another not-a-polymorphic-type), but where one or the other element can be zero-sized and not waste memory. It's an aggregation tool.For the 3rd time, why do you need it to have 0 size? I don't know what you mean by "handling" it.Can I ask again, in a different way, why do you need the 0 size?To handle base structs with no members.
Jun 18 2019
On Wed, Jun 12, 2019 at 11:29 PM Manu <turkeyman gmail.com> wrote:On Wed, Jun 12, 2019 at 10:25 PM Walter Bright via Digitalmars-d <digitalmars-d puremagic.com> wrote:What are we so afraid of? I don't understand the resistance to this *at all*... people talk about slicing, which is a pretty worthless baseline argument; it's totally possible in C++ and I've never heard a single case of anyone ever having that problem in my life, at work, at home, or even on the internet (yes, I'm sure I would find if I deliberately went looking). I'm only aware the concept has a name because I've seen it written in a book somewhere. It's 99.9999% not-even-remotely-a-problem, it's only a 'theoretical' problem. What if we dis-allowed implicit casting structs to base type? I mean, nothing else about it is polymorphic in nature... not-allowing implicit casting to base type would not cause problems in any use I can imagine. This should obviously be a compile error: struct A { int x; } struct B : A { int y; } B b; A a = b; // <- obviously an errorOn 6/11/2019 11:19 AM, Manu wrote:I hate wasting 8 bytes needlessly. Almost every struct I write is carefully packed and aligned to 16, 32, or 64 bytes and allocated in pools... that's 50%, 25%, or 12.5% memory wastage. There's also ABI compatibility with existing C++ where this is super-common. Consider that user-supplied <Allocator> is a base of every STL container, that's one case where I've had to deploy the static if hack a lot. Those are absolutely not polymorphic types, and you couldn't make that mistake no matter how hard you squinted. They sometimes use a helper called a 'packed pair' in the STL, which is like std::pair (obviously another not-a-polymorphic-type), but where one or the other element can be zero-sized and not waste memory. It's an aggregation tool.For the 3rd time, why do you need it to have 0 size? I don't know what you mean by "handling" it.Can I ask again, in a different way, why do you need the 0 size?To handle base structs with no members.
Jun 12 2019
On Thursday, 13 June 2019 at 06:43:44 UTC, Manu wrote:What are we so afraid of? I don't understand the resistance to this *at all*... people talk about slicing, which is a pretty worthless baseline argument; it's totally possible in C++ and I've never heard a single case of anyone ever having that problem in my life, at work, at home, or even on the internet (yes, I'm sure I would find if I deliberately went looking). I'm only aware the concept has a name because I've seen it written in a book somewhere. It's 99.9999% not-even-remotely-a-problem, it's only a 'theoretical' problem. What if we dis-allowed implicit casting structs to base type? I mean, nothing else about it is polymorphic in nature... not-allowing implicit casting to base type would not cause problems in any use I can imagine. This should obviously be a compile error: struct A { int x; } struct B : A { int y; } B b; A a = b; // <- obviously an errorSeveral topics have come up that imho all may have merit and bit size (related to Manu's application but in general having unsafe consequences. Regarding the OP abut struct inheritance, I think we need to specify the request better, and then discuss more objectively its pros and cons, and if there are advantages, what restrictions are needed to avoid pitfalls. We are also getting confused with words: we aren't placing the same meaning on the same words, specially "polymorphism". I will use it with the meaning of one type used in place of another (i.e. subtyping), while Manu seems to restrict the term to when this is late/dynamically bound. I'm not clear how much polymorphism (not only dynamic) this would carry or we'd like it to? Not just implicit casting or copy constructors (again let's be general and leave the OP application aside), but what about passing derived structs by ref or pointer? And What about destructors? After all a derived struct would indeed have the data and methods of the base one, so it is open to consideration that it could be (statically) polymorphic, either by ref or by copy or both. I am in favor of not being dogmatic, but if D introduced this it would be treading unproven territory; so it deserves a lot of thinking so that we don't introduce pitfalls into the language; but I am in favor of D having more good features and DRY. In C++ everything is allowed of course, but a virtual destructor is absolutely advised when inheriting. (Besides the fact that dynamic polymorphism and OOP themselves are nowadays out of fashion with the dominant C++ and D crowds.) Most times this question is discussed in the context of inheriting STL containers, which goes at least against the design intent of the STL in particular; but again our question is more general. .NET has quite the same kind of structs as D, and forbids structs to inherit custom types (although they can implement interfaces!). The CLI specification says only this is to "avoid dealing with the complications of value slicing ... allow for more efficient implementation without severely compromising functionality."
Jun 13 2019
On 13.06.19 08:43, Manu wrote:What are we so afraid of? I don't understand the resistance to this *at all*...I think a lot of the default opposition to new features (especially if they can be implemented with a moderate amount of user code) is about DMD compiler complexity, about adding new things to a code base which already suffers quite a bit from incidental complexity. (E.g., I learned last week that there are multiple different ways to infer function attributes. Some of them are quite broken, but I wasn't able to get rid of the special and broken `pure` inference without breaking the test suite, within the allotted time.)people talk about slicing, which is a pretty worthless baseline argument; it's totally possible in C++ and I've never heard a single case of anyone ever having that problem in my life, at work, at home, or even on the internet (yes, I'm sure I would find if I deliberately went looking). I'm only aware the concept has a name because I've seen it written in a book somewhere. It's 99.9999% not-even-remotely-a-problem, it's only a 'theoretical' problem. ...Slicing is only a problem if you have a vtable.
Jun 13 2019
On 6/13/2019 5:03 AM, Timon Gehr wrote:I think a lot of the default opposition to new features (especially if they can be implemented with a moderate amount of user code) is about DMD compiler complexity, about adding new things to a code base which already suffers quite a bit from incidental complexity.D has a TON of features. And yet every single day, people demand ever more features. How can this possibly work without turning D (and the compiler) into a unusable mess. I have no choice but to constantly say "no". As for struct inheritance, it seems what Manu really wants isn't struct inheritance at all, it is zero sized structs having zero size when they are used as fields. First off, he has a workaround for it. I agree it's not very pretty, but it works and he is not blocked. That moves it way down on the priority list. Secondly, there are template mixins, which have zero size.
Jun 18 2019
On 18.06.19 11:23, Walter Bright wrote:On 6/13/2019 5:03 AM, Timon Gehr wrote:As far as I can tell, a lot of the incidental complexity is introduced in bug fixes. Furthermore, the issue is: - features whose implementation is spread all over the code base without an easy way to find all components of their implementation. - features that should work the same (e.g. nogc inference and pure inference) that have a different and incompatible implementation.I think a lot of the default opposition to new features (especially if they can be implemented with a moderate amount of user code) is about DMD compiler complexity, about adding new things to a code base which already suffers quite a bit from incidental complexity.D has a TON of features. And yet every single day, people demand ever more features. How can this possibly work without turning D (and the compiler) into a unusable mess.I have no choice but to constantly say "no". ...I agree it is a useful default stance.
Jun 18 2019
On 6/18/2019 5:07 AM, Timon Gehr wrote:As far as I can tell, a lot of the incidental complexity is introduced in bug fixes.I've caught a lot of PRs for fixes that were incorrect. A lot slip by me.Furthermore, the issue is: - features whose implementation is spread all over the code base without an easy way to find all components of their implementation.You're absolutely right on that. I really want to encapsulate this stuff - most recently https://github.com/dlang/dmd/pull/9993- features that should work the same (e.g. nogc inference and pure inference) that have a different and incompatible implementation.Generally that is the result of incremental accretion of features.
Jun 18 2019
On Tue, Jun 18, 2019 at 7:25 PM Walter Bright via Digitalmars-d <digitalmars-d puremagic.com> wrote:On 6/13/2019 5:03 AM, Timon Gehr wrote:I'm pretty much just into feature uniformity at this stage. D's biggest problem from my perspective is "weird shit", mostly non-uniform arbitrary limitations and strange edge cases. And also that shared doesn't work.I think a lot of the default opposition to new features (especially if they can be implemented with a moderate amount of user code) is about DMD compiler complexity, about adding new things to a code base which already suffers quite a bit from incidental complexity.D has a TON of features. And yet every single day, people demand ever more features. How can this possibly work without turning D (and the compiler) into a unusable mess. I have no choice but to constantly say "no".As for struct inheritance, it seems what Manu really wants isn't struct inheritance at all, it is zero sized structs having zero size when they are used as fields.As base structs specifically. I really want struct inheritance, and zero sized fields does happen to be one thing that falls out of that. There are 2 things I hate about it; one is the crappy static-if hack required to deal with zero-sized bases, the other is that I have to use `alias this` to describe a base. alias this *should* be a very niche feature, but instead we abuse it in lieu of struct inheritance, and no way to perform implicit conversion. In both cases it's a gross code smell, and I hate it.First off, he has a workaround for it. I agree it's not very pretty, but it works and he is not blocked. That moves it way down on the priority list.I agree. The thread was just to re-iterate my strong discontent, and frankly, boredom with the situation.Secondly, there are template mixins, which have zero size.That's feels even worse than my crappy hack to me.
Jun 18 2019
On Tuesday, 18 June 2019 at 12:17:36 UTC, Manu wrote:As base structs specifically. I really want struct inheritance, and zero sized fields does happen to be one thing that falls out of that. There are 2 things I hate about it; one is the crappy static-if hack required to deal with zero-sized bases, the other is that I have to use `alias this` to describe a base. alias this *should* be a very niche feature, but instead we abuse it in lieu of struct inheritance, and no way to perform implicit conversion. In both cases it's a gross code smell, and I hate it.It might be because I write a lot less generic code than you do, but I really don't understand why you lend so much importance to implicit conversion. XavierAP's question is particularly relevant here:What is the benefit of struct A { void fun(); }; struct B :A {}; B b; b.fun; compared to struct A {}; struct B { A a; }; B b; b.a.fun;Like, seriously, I might be missing something, but I don't get it. Can you cite some use case where inheritance is convenient but composition isn't? Ideally an actual use case that came up in a project?
Jun 18 2019
On Tuesday, 18 June 2019 at 18:39:41 UTC, Olivier FAURE wrote:On Tuesday, 18 June 2019 at 12:17:36 UTC, Manu wrote:I'm not against struct inheritance... Even though I don't get or haven't looked into Manu's application, and I rather try to understand the pros and cons in general, my impression is that he knows what he's talking about and has likely considered plenty of implications elsewhere, but he's tired of discussing over again. :p In very general terms there are potential risks when things happen implicitly. A new feature with such effects is likelier to have unintended consequences at least in corner cases. That's where my questions were coming from. But my initial guess is that there might be nothing wrong with struct inheritance, at least if the value semantics are preserved. And I do agree with Manu that alias this should be a very niche feature, and we are using it for structs as clumsier, dirtier and more verbose way to get the regular (static) polymorphism that we'd better implement by inheritance if possible. Walter himself has admitted (in the multiple alias this thread) that alias this can be equivalent to inheritance (and that's argument enough why multiple's bad). Something else in these discussions, the current fashion in CS is that inheritance is bad and you should use composition instead every single time -- just like the past OOP fad said the opposite against C. I agree that too deep or extensive inheritance hierarchies are a bad pattern, but inheritance isn't bad in itself or in moderation. And again this discussion gets mixed up with C++ people who design classes inheriting from the STL. Since it's probably a bad idea to extend a library following the opposite architecture patterns and design intent of the library, it's probably a bad idea to inherit from the STL (and the lack of virtual constructors doesn't help), but this get mixed up with the idea that inheriting itself would be always a bad idea for any architecture. And the fact that the STL was not made with an (even non virtual) inheritance architecture (*ahem* std::basic_string *ahem*) also makes inheritance less popular -- nowadays in comparison with composition, even though STL uses templates not composition.alias this *should* be a very niche feature, but instead we abuse it in lieu of struct inheritance, and no way to perform implicit conversion. In both cases it's a gross code smell, and I hate it.It might be because I write a lot less generic code than you do, but I really don't understand why you lend so much importance to implicit conversion. XavierAP's question is particularly relevant here:What is the benefit of struct A { void fun(); } struct B :A {} B b; b.fun; compared to struct A {} struct B { A a; } B b; b.a.fun;Like, seriously, I might be missing something, but I don't get it. Can you cite some use case where inheritance is convenient but composition isn't? Ideally an actual use case that came up in a project?
Jun 19 2019
On 6/18/2019 5:17 AM, Manu wrote:The more I've read about and studied concurrent programming issues, I tend to
Jun 18 2019
On Wed, Jun 19, 2019 at 5:55 AM Walter Bright via Digitalmars-d <digitalmars-d puremagic.com> wrote:On 6/18/2019 5:17 AM, Manu wrote:On the plus side, a working shared solution is only a couple of lines away. We don't need anything fancy, actually less fancy than how it is now; just remove read/write, and let us see what we can do with the library (a lot). If/when we run into limitations with regards to library tooling, we can see how it looks from there.The more I've read about and studied concurrent programming issues, I tend to
Jun 18 2019
On Tuesday, 18 June 2019 at 09:23:45 UTC, Walter Bright wrote:As for struct inheritance, it seems what Manu really wants isn't struct inheritance at all, it is zero sized structs having zero size when they are used as fields.Quick question, have you considered the following syntax: align(0) struct MyEmptyStruct {}; or some other means of saying "I don't intend to take this struct's address, I don't mind if it takes zero bytes of space"?
Jun 18 2019
On Thursday, 13 June 2019 at 06:43:44 UTC, Manu wrote:This should obviously be a compile error: struct A { int x; } struct B : A { int y; } B b; A a = b; // <- obviously an errorIt doesn't become so obvious when you can implicitly convert to the base type. A foo(ref A a) { return a; } B b; A a = foo(b);
Jun 13 2019
On Thu, Jun 13, 2019 at 7:35 AM Exil via Digitalmars-d <digitalmars-d puremagic.com> wrote:On Thursday, 13 June 2019 at 06:43:44 UTC, Manu wrote:So don't implicitly convert to the base type? B extends A, but I don't think it's a kind of A as for polymorphic classes.This should obviously be a compile error: struct A { int x; } struct B : A { int y; } B b; A a = b; // <- obviously an errorIt doesn't become so obvious when you can implicitly convert to the base type. A foo(ref A a) { return a; } B b; A a = foo(b);
Jun 13 2019
On Thursday, 13 June 2019 at 22:13:51 UTC, Manu wrote:So don't implicitly convert to the base type? B extends A, but I don't think it's a kind of A as for polymorphic classes.So you want class Foo : BaseClass {} and struct Bar : BaseStruct {} to produce two different results?
Jun 13 2019
On Thu, Jun 13, 2019 at 9:20 PM Mike Parker via Digitalmars-d <digitalmars-d puremagic.com> wrote:On Thursday, 13 June 2019 at 22:13:51 UTC, Manu wrote:Well, one's a class and the other's a struct, and that means what it means.So don't implicitly convert to the base type? B extends A, but I don't think it's a kind of A as for polymorphic classes.So you want class Foo : BaseClass {} and struct Bar : BaseStruct {} to produce two different results?
Jun 13 2019
On Friday, 14 June 2019 at 05:59:25 UTC, Manu wrote:It means inconsistency, IMO, and a new violation of the principle of least astonishment. I have nothing against the behavior you want, but if it's going to behave differently from polymorphic inheritance, then it should look different.So you want class Foo : BaseClass {} and struct Bar : BaseStruct {} to produce two different results?Well, one's a class and the other's a struct, and that means what it means.
Jun 14 2019
On Thursday, 13 June 2019 at 22:13:51 UTC, Manu wrote:So don't implicitly convert to the base type? B extends A, but I don't think it's a kind of A as for polymorphic classes.What is the benefit of struct A { void fun(); }; struct B :A {}; B b; b.fun; compared to struct A {}; struct B { A a; }; B b; b.a.fun; Less typing is good but stuff happening magically/unexpectedly for a neutral reader of the code (e.g. implicit casts) is not. And if on the other hand, !is(B:A), then what is the advantage, and the use case? Your OP pattern may have good alternatives that don't repeat code either, but produce more explicitly readable code?
Jun 14 2019
On Friday, 14 June 2019 at 14:47:15 UTC, XavierAP wrote:On Thursday, 13 June 2019 at 22:13:51 UTC, Manu wrote:Moreover, even if your inheritance did not produce (static) polymorphism in the hard sense i.e. !is(B:A), it would in the duck-typed sense, in templates! So inheritance without polymorphism is inconsistent. struct A { void fun(); }; struct B :A {}; void gun(A x) { x.fun; } void hun(T)(T x) { x.fun; } B b; b.gun; // error? b.hun; // okSo don't implicitly convert to the base type? B extends A, but I don't think it's a kind of A as for polymorphic classes.Less typing is good but stuff happening magically/unexpectedly for a neutral reader of the code (e.g. implicit casts) is not. And if on the other hand, !is(B:A), then what is the advantage, and the use case?
Jun 14 2019
On 6/11/19 3:56 AM, Walter Bright wrote:Can I ask again, in a different way, why do you need the 0 size?In games programming, you frequently have (at least) one of two things: A. A limited-resource embedded system that you're wringing every last bit of memory and performance out of. B. At least several tens of gigabytes worth of content. Either way, this makes *ANY* wasted per-instance overhead unacceptable.
Jun 11 2019
On 6/11/2019 9:56 PM, Nick Sabalausky (Abscissa) wrote:Either way, this makes *ANY* wasted per-instance overhead unacceptable.I'm curious what Manu's reason is. Does he have billions of them?
Jun 12 2019
On Sunday, 9 June 2019 at 08:05:34 UTC, Manu wrote:Imagine if we could just write: struct DerivedStruct : BaseStruct { // derived members //... } Just imagine!+1 I dream of being able to do struct DerivedStruct: SomeInterface, but what you are asking is also something I was wishing for years...
Jun 10 2019
On Sunday, 9 June 2019 at 08:05:34 UTC, Manu wrote:I am really really tired of this pattern: struct DerivedStruct { static if (BaseStruct.tupleof.length > 0) BaseStruct base; else ref inout(BaseStruct) base() inout { return *cast(inout(BaseStruct)*)&this; } alias base this; // derived members //... } Imagine if we could just write: struct DerivedStruct : BaseStruct { // derived members //... } Just imagine!I like the idea! I use the `alias this` idiom everywhere, and it is not too evident to new people coming from other languages, there is an overhead in explaining and understanding what that thing does, which is simple by itself. However, I do see some issues with using the existing inheritance syntax, as it creates some confusions and maybe some false expectations. I would like to have something like: struct Derived mixin Base { } which is more clear in the intent and reuses a well established concept in the language.
Jun 11 2019
On Sunday, 9 June 2019 at 08:05:34 UTC, Manu wrote:I am really really tired of this pattern: struct DerivedStruct { static if (BaseStruct.tupleof.length > 0) BaseStruct base; else ref inout(BaseStruct) base() inout { return *cast(inout(BaseStruct)*)&this; } alias base this; // derived members //... } Imagine if we could just write: struct DerivedStruct : BaseStruct { // derived members //... } Just imagine!That is a good idea (ahem… )but what about multiple derived classes ? I think the composition approach could help us by the use of the delegator concept from Ruby. With a such approach a struct can: - own multiple base/child struct/component - choose which method to forward to the base/child struct/component So at the and a such feature could be a sugar syntax of template Proxy: https://dlang.org/library/std/typecons/proxy.html Reference: - ruby delegator: https://blog.lelonek.me/how-to-delegate-methods-in-ruby-a7a71b077d99 - ruby delagator all supported methods: https://rubyreferences.github.io/rubyref/stdlib/patterns/delegate.html As Example struct Person { … int get_age(){…} } struct Career{ … int get_experience(){…} } struct Employee{ delegate: get_age, to: _person delegate: get_experience, to: _career immutable Person _person; immutable Career _career; this( immutable Person person , immutable Career career ){ _person = person; _career = career; } }
Jun 21 2019
On Friday, 21 June 2019 at 22:19:12 UTC, bioinfornatics wrote:struct Employee{ delegate: get_age, to: _person delegate: get_experience, to: _career immutable Person _person; immutable Career _career;Listing all methods isn't very helpful, if that is the suggestion. Then a more consistent syntax would be struct Employee { alias getage = _person.getage; alias get_experience = _career.get_experience; Yet, that does not solve the MI problems. Some are: 1. What to do if you both superclasses has a length() method. 2. What do do if both superclasses has used the same method name for unrelated concepts? If there is no overlap semantically then problem 1 and 2 can be resolved with a cast to the super class, so that you get the right method. However, what if the subclass has to modify them to retain the correct semantics? Which is really what MI problems are about. Then you need som way of overloading a function that calls a specific attribute of a struct. So you need overloading on attributes, not only overloading on types, yet you also need a reference to the parent struct. So you need to be able to do something like int length(SubStruct.attributename* this) { this.parent } Ola.
Jun 21 2019
On Saturday, 22 June 2019 at 06:29:43 UTC, Ola Fosheim Grøstad wrote:Then you need som way of overloading a function that calls a specific attribute of a struct. So you need overloading on attributes, not only overloading on types, yet you also need a reference to the parent struct. So you need to be able to do something like int length(SubStruct.attributename* this) { this.parent }In other words, you need static virtual methods. Perhaps a better syntax would be something along the lines of: struct SubClass { int _length; inherit SuperClass1 { int length(){ this.super.length() + this.parent._length} } attribute1; inherit SuperClass2 { int length(){ this.super.length() - this.parent._length} } attribute2; } It is difficult to find a syntax that isn't confusing. Probably better to do it with interfaces.
Jun 21 2019
On Saturday, 22 June 2019 at 06:29:43 UTC, Ola Fosheim Grøstad wrote:On Friday, 21 June 2019 at 22:19:12 UTC, bioinfornatics wrote:Yes you are right, previously I show one sample case, when you want to choose which method will be forwarded to the component. If you need to forward all child methods from the base struct you can use the template proxy from dlang or alias this. For MI case, as here is a composition: (i)a compiler's warning could be raised if method shadow another one (ii) a sugar syntax to "alias" to synonym method name delegate: Person.size, to: size delegate: Career.size, to: length (iii) a sugar syntax to forward all delegate: Person Is an example of syntax using annotation is possible tostruct Employee{ delegate: get_age, to: _person delegate: get_experience, to: _career immutable Person _person; immutable Career _career;Listing all methods isn't very helpful, if that is the suggestion. Then a more consistent syntax would be struct Employee { alias getage = _person.getage; alias get_experience = _career.get_experience; Yet, that does not solve the MI problems. Some are: 1. What to do if you both superclasses has a length() method. 2. What do do if both superclasses has used the same method name for unrelated concepts? If there is no overlap semantically then problem 1 and 2 can be resolved with a cast to the super class, so that you get the right method. However, what if the subclass has to modify them to retain the correct semantics? Which is really what MI problems are about. Then you need som way of overloading a function that calls a specific attribute of a struct. So you need overloading on attributes, not only overloading on types, yet you also need a reference to the parent struct. So you need to be able to do something like int length(SubStruct.attributename* this) { this.parent } Ola.
Jun 21 2019
If we want multiple inheritance or even virtual methods in structs, completely new and severe problems appear. And I don't think these patterns have utility that justifies these problems or even their existence alone. Single struct inheritance with no virtual methods presents in my opinion no problems, and it would be in many cases a better, more concise, boilerplate-less, clearer, cleaner way to accomplish the type extension and not repeating oneself that currently we can do only by composition and explicit forwarding, alias this, or macro-ish template mixins. On Saturday, 22 June 2019 at 06:29:43 UTC, Ola Fosheim Grøstad wrote:On Friday, 21 June 2019 at 22:19:12 UTC, bioinfornatics wrote:Explicit forwarding is already/always possible. These syntaxes are not so more concise than auto getAge() { return _person.getAge(); } So I'd see no point in burdening D with adding such candy features.struct Employee{ delegate: get_age, to: _person delegate: get_experience, to: _career immutable Person _person; immutable Career _career;Listing all methods isn't very helpful, if that is the suggestion. Then a more consistent syntax would be struct Employee { alias getage = _person.getage; alias get_experience = _career.get_experience;
Jun 22 2019
On Saturday, 22 June 2019 at 07:10:26 UTC, XavierAP wrote:If we want multiple inheritance or even virtual methods in structs, completely new and severe problems appear. And I don't think these patterns have utility that justifies these problems or even their existence alone. Single struct inheritance with no virtual methods presents in my opinion no problems, and it would be in many cases a better, more concise, boilerplate-less, clearer, cleaner way to accomplish the type extension and not repeating oneself that currently we can do only by composition and explicit forwarding, alias this, or macro-ish template mixins. On Saturday, 22 June 2019 at 06:29:43 UTC, Ola Fosheim Grøstad wrote:Thanks for your insight. So I have a question what solve the struct inheritance which can not be done by the use of method forwarding? To me the template proxy is the way to go. They are no needs to extend the dlang syntax. Case 1: too few people know it Case 2: struct inheritance solve things that can not be done using the proxy https://dlang.org/library/std/typecons/proxy.htmlOn Friday, 21 June 2019 at 22:19:12 UTC, bioinfornatics wrote:Explicit forwarding is already/always possible. These syntaxes are not so more concise than auto getAge() { return _person.getAge(); } So I'd see no point in burdening D with adding such candy features.struct Employee{ delegate: get_age, to: _person delegate: get_experience, to: _career immutable Person _person; immutable Career _career;Listing all methods isn't very helpful, if that is the suggestion. Then a more consistent syntax would be struct Employee { alias getage = _person.getage; alias get_experience = _career.get_experience;
Jun 24 2019
On Monday, 24 June 2019 at 16:13:05 UTC, bioinfornatics wrote:Thanks for your insight. So I have a question what solve the struct inheritance which can not be done by the use of method forwarding?Less typing (cleaner, better code) and subtyping/polymorphism. Of course every language feature could be implemented from scratch in C. But if we're using other languages it's because their features are useful.To me the template proxy is the way to go. They are no needs to extend the dlang syntax. Case 1: too few people know it Case 2: struct inheritance solve things that can not be done using the proxy https://dlang.org/library/std/typecons/proxy.htmlProxy behaves (is purposely designed to behave) quite differently from inheritance... But to answer the general proposition that it's best to eliminate inheritance and implement it from templates, I think it makes no sense in principle because templates are more complex, both in code and under the hood (of the compiler specially). Inheritance (without virtual/dynamic dispatch) is as simple as aligning a few bytes together with the base type's ones. There are fads in patterns, and nowadays people are against inheritance. Little ago templates were the answer to everything, just like OOP was in the 90s (of course templates are extremely useful). Their use pushed compilation times and code readability out of orbit. Nowadays quite some people are reacting by going back to C, plain composition, and their dogma is that dangling pointers are the least problem. D was purposely created not to follow one single paradigm, but to offer all modern, proven ones to discerning programmers.
Jun 24 2019
On Monday, 24 June 2019 at 21:13:17 UTC, XavierAP wrote:Nowadays quite some people are reacting by going back to C, plain composition, and their dogma is that dangling pointers are the least problem.These people are insane. Long compile times and high compile memory usage create problems for developers. Dangling pointers create problems for developers AND users (very nasty problems at that). C cannot die quickly enough. We should be working to kill it, not bring about its resurgence.
Jun 24 2019
On Monday, 24 June 2019 at 21:20:21 UTC, Meta wrote:On Monday, 24 June 2019 at 21:13:17 UTC, XavierAP wrote:C++ is more so the one with how long it takes to compile. C isn't that bad. I don't see anything replacing C, there are a number of different languages that could but they are all fragmented. DMD can eat a lot of memory, it also isn't very efficient. static foreach(i; 0 .. 0xFFFF) {} the above code eats up over 12 GB of RAM. That's all my free RAM + whatever it is using on my drive. It also takes a REALLY long time to execute, at least an hour. I gave up after that. Spends almost all of it's time doing Array operations. DMD has a really weird implementation of Array, looks like it was implemented possibly in D1 days. Reserve(int) is additive, sure fine w/e. Passing around arrays as points, so need to dereference them to actually use them... Then you have insert(Range) that does a reserve(), which allocates new memory, copies all the data. Then the insert moves all the data it just copied. Sure the code is simpler but it has horrible performance, especially when there is a loop that is constantly adding and removing from the front/middle of the array.Nowadays quite some people are reacting by going back to C, plain composition, and their dogma is that dangling pointers are the least problem.These people are insane. Long compile times and high compile memory usage create problems for developers. Dangling pointers create problems for developers AND users (very nasty problems at that). C cannot die quickly enough. We should be working to kill it, not bring about its resurgence.
Jun 24 2019
On Sunday, 9 June 2019 at 08:05:34 UTC, Manu wrote:Imagine if we could just write: struct DerivedStruct : BaseStruct { // derived members //... } Just imagine!Mhmm... I'd think struct inheritance would follow the original C++'s ideology. So probably: 1) No Virtual functions. All functions are FINAL (replacing) 2) No polymorphism. 3) Limited casting (Casting up/back is easier than casting down, with space limitations in mind), though casting could simply be disallowed but that seems unlikely when you get low level. In such a case you could build a base struct and then add onto it for several structs behaviors. Being able to avoid using the GC as much as possible that would help. Also most of the functions/structures are basically copy/pasted with overriding functions completely replacing the previous ones. I've been wanting this for a while. I had a prototype set of templates to do this very thing! But... it no longer works, hasn't since... oh i don't remember. I'd have to pull the old files out... I'd probably ask a debugging feature where you could output the new finalized struct in it's full source code or maybe rather just it's API specifying what functions/variables come from where, so you get a clear picture of what you're working with if you inherit several times/deep.
Jul 01 2019
On Tuesday, 2 July 2019 at 04:54:07 UTC, Era Scarecrow wrote:1) No Virtual functions. All functions are FINAL (replacing) 2) No polymorphism. 3) Limited casting (Casting up/back is easier than castingAnd looking at my old notes... Might make it where the data size can't change. This crypto stuff used to work in 10/2012, or with DMD 2.060 From the polymorph.d --- auto crypto = PolyCryptoBase.factory("CryptoROT13"); crypto.setString("(Whfg n yvggyr pelcgb grfg)"); crypto.encipher; assert(crypto.data.crypted == "(Just a little crypto test)"); --- Here's a crypto example of the actual structs /** This is not intended as a serious crypto library, just enough to test several factors to ensure the polymorphic nature is being done. As other items need to be tested this crypto will be improved to handle those tests.*/ struct PolyCryptoBase { ///Enum, _prefix and _types don't exist until this calls. mixin(expandTypes("Data", "Poly_", "CryptoBase,CryptoXOR13,CryptoROT13")); /// struct Data { Enum polyMorphType; /// string original; /// char[] crypted; ///mutable copy } Data data; /// ///Seems opCmp opEquals and similar functions go in the poly base. That's livable. ///if not, forward reference to Poly_opCmp mixin PolyMorphicCompare!(PolyCryptoBase); mixin PolyMorphic!("smartmerged.polymorphicstruct_crypto", PolyCryptoBase, Data, "data"); /// } /// struct CryptoBase { mixin PolyMorphicInclude!(PolyCryptoBase); /// ///Seems opCmp opEquals and similar functions go in the poly base. That's livable. ///if not, forward reference to Poly_opCmp int Poly_opCmp(ref const PolyCryptoBase rhs) const { return data.original.length - rhs.data.original.length; } ///if it matches the original string bool isCrypted() property pure safe nothrow{ return data.original != data.crypted; } ///Does basic enciphering, individual letters only static void Poly_cipherChar(ref char c) pure safe nothrow { c ^= 127; } ///set the plaintext (resetting crypted text as well) void setString(string input) property { data.original = input; data.crypted = input.dup; } ///encrypt cipher string (which done twice will decrypt it) void encipher() property { foreach(ref ch; data.crypted) { this.cipherChar(ch); } } } /// struct CryptoXOR13 { mixin PolyMorphicInclude!(PolyCryptoBase);/// /**non matching signatures, but still compatible requires 'static' or const to work, otherwise potential for only calling a different version may apply making some bugs hard to find.*/ static void cipherChar(ref char c) pure safe { c ^= 13; } } Yeah a little long winded, but it did work as a concept... I can share the old full sources if you want.
Jul 01 2019