digitalmars.D - Why is separating class ind struct is bad?
- Suliman (7/7) Mar 25 2016 Here on forum I have found very interesting mention from
- Suliman (2/2) Mar 25 2016 Sorry about Volta mention, I just make copy-past from my question
- Jonathan M Davis via Digitalmars-d (10/17) Mar 26 2016 I expect that you're referring to a recent thread where interfacing with...
- Dicebot (5/7) Mar 26 2016 I disagree with this statement. The very presence of utils like
- Jonathan M Davis via Digitalmars-d (21/28) Mar 26 2016 Rebindable is definitely a sign that there's a problem with how it was
- Dicebot (11/15) Mar 26 2016 That I disagree with too. Putting class on stack simply means
- Iain Buclaw via Digitalmars-d (10/14) Mar 26 2016 D code in general
- Walter Bright (19/26) Mar 26 2016 I've worked a lot with C++ aggregates that were confused about whether t...
- Dicebot (21/58) Mar 28 2016 It is hard to argue that but I have never encountered any issues from
- Walter Bright (15/33) Mar 29 2016 My experience is the opposite. I've found it quick & easy to attempt dif...
- Danni Coy via Digitalmars-d (8/9) Mar 29 2016 This is in the context of users migrating from C++, and it is bad in
Here on forum I have found very interesting mention from Alexandrescu that: "Rust has two advantages I can think of: it doesn't have the struct/class split that D does". Could anybody explain why it's bad, and maybe till Volta in WIP it's not later to change it. Could anybody explain what this mean and why this way is not modern?
Mar 25 2016
Sorry about Volta mention, I just make copy-past from my question there.
Mar 25 2016
On Saturday, March 26, 2016 06:26:44 Suliman via Digitalmars-d wrote:Here on forum I have found very interesting mention from Alexandrescu that: "Rust has two advantages I can think of: it doesn't have the struct/class split that D does". Could anybody explain why it's bad, and maybe till Volta in WIP it's not later to change it. Could anybody explain what this mean and why this way is not modern?I expect that you're referring to a recent thread where interfacing with C++ was being discussed and how D compares to Rust in that regard. And when talking specifically about interfacing with C++, D's separation of structs and classes is potentially a problem, because that's not what C++ does. So, we're either limited in some respects with how D interfaces with C++ and/or the inferfacing code becomes more complicated. So, while the separation between structs and classes definitely good for D code in general, it does pose a problem when interfacing with C++. - Jonathan M Davis
Mar 26 2016
On Saturday, 26 March 2016 at 07:42:43 UTC, Jonathan M Davis wrote:So, while the separation between structs and classes definitely good for D code in generalI disagree with this statement. The very presence of utils like `Rebindable` or `scoped` indicates this wasn't a very clean design choice, not in a way it was implemented at least.
Mar 26 2016
On Saturday, March 26, 2016 08:03:21 Dicebot via Digitalmars-d wrote:On Saturday, 26 March 2016 at 07:42:43 UTC, Jonathan M Davis wrote:Rebindable is definitely a sign that there's a problem with how it was implemented, but it's also something that we've been able to work around. And while scoped may make sense in rare cases, pretty much by definition, if you're putting an object on the heap, polymorphism is not involved, and therefore it's completely unnecessary to use a class. Really, it's just an attempt to reuse code that's in a class in a context where polymorphism is unnecessary. So, arguably, needing scoped is a sign of bad design in the code that's using it. Certainly, if it's needed frequently, then the types being used with it really should have been structs. I won't disagree that the separation of classes and structs is not without its downsides, and the need for Rebindable does show that they way we implemented it wasn't as elegant as it arguably should have been, but overall, I think that the separation is a definite improvement over C++'s approach. Unless you use scoped (which is system), object slicing is a non-issue thanks to that separation, and since an object that needs polymorphism really doesn't make sense on the stack anyway, it separates user-defined types from the inheritance mess in the cases where it's unnecessary while still allowing inheritance to be used in a safe manner when it makes sense. - Jonathan M DavisSo, while the separation between structs and classes definitely good for D code in generalI disagree with this statement. The very presence of utils like `Rebindable` or `scoped` indicates this wasn't a very clean design choice, not in a way it was implemented at least.
Mar 26 2016
On Saturday, 26 March 2016 at 08:31:41 UTC, Jonathan M Davis wrote:And while scoped may make sense in rare cases, pretty much by definition, if you're putting an object on the heap, polymorphism is not involved, and therefore it's completely unnecessary to use a class.That I disagree with too. Putting class on stack simply means that current scope will outlive the usage of class instance - it has nothing to do with polymorphism. It is one of many memory optimizations. To explain a bit more, what I would consider convenient is to limit struct/class distinction to polymorphism exclusively, with not extra implications. So that you can still can do `MyClass on_stack;` (any `MyClass` is treated as type of object) but passing it to function wouldn't compile unless `ref` is also used.
Mar 26 2016
On 26 Mar 2016 9:05 am, "Dicebot via Digitalmars-d" < digitalmars-d puremagic.com> wrote:On Saturday, 26 March 2016 at 07:42:43 UTC, Jonathan M Davis wrote:D code in generalSo, while the separation between structs and classes definitely good forI disagree with this statement. The very presence of utils like`Rebindable` or `scoped` indicates this wasn't a very clean design choice, not in a way it was implemented at least. Isn't that more a slam at the "deprecations" that still have no compiler enforcement 6 years down the line, and not directly related to class storage itself? I don't think Rebindable is a good example to show what is wrong with classes. More in the direction of head(const).
Mar 26 2016
On 3/26/2016 1:03 AM, Dicebot wrote:On Saturday, 26 March 2016 at 07:42:43 UTC, Jonathan M Davis wrote:I've worked a lot with C++ aggregates that were confused about whether they were a floor wax or a dessert topping, and talking to their implementors showed they had little idea of the consequences (and bugs) of those choices. D's design has debatable flaws, but I'm confident they are much diminished over the flaws and traps in the C++ design.So, while the separation between structs and classes definitely good for D code in generalI disagree with this statement. The very presence of utils like `Rebindable` or `scoped` indicates this wasn't a very clean design choice, not in a way it was implemented at least.what I would consider convenient is to limit struct/class distinction topolymorphism exclusively, with not extra implications. So that you can still can do `MyClass on_stack;` (any `MyClass` is treated as type of object) but passing it to function wouldn't compile unless `ref` is also used. So where it is allocated you'd have 'MyClass' and everywhere it is used you'd have 'ref MyClass'. There are a lot of consequences of this, such as: 1. Want to switch between a class and a struct? You've got lots of editing to do. 2. You'd have to invent a way to do 'alias ref MyClass T;' 3. ref has special semantics in D about being a non-escaping pointer. This means issues if you want a 'ref MyClass' field in a struct. I'm not saying your idea is necessarily bad, but there is a heckuva lot to think about in interactions with other features. It's not so easy to produce a design that doesn't have a nail sticking up here or there. I don't know of any language that succeeded in that.
Mar 26 2016
On 03/26/2016 02:01 PM, Walter Bright wrote:On 3/26/2016 1:03 AM, Dicebot wrote:It is hard to argue that but I have never encountered any issues from actual confusion between struct and class in C++ (because there isn't any real difference), only from misusage of virtual types.On Saturday, 26 March 2016 at 07:42:43 UTC, Jonathan M Davis wrote:I've worked a lot with C++ aggregates that were confused about whether they were a floor wax or a dessert topping, and talking to their implementors showed they had little idea of the consequences (and bugs) of those choices. D's design has debatable flaws, but I'm confident they are much diminished over the flaws and traps in the C++ design.So, while the separation between structs and classes definitely good for D code in generalI disagree with this statement. The very presence of utils like `Rebindable` or `scoped` indicates this wasn't a very clean design choice, not in a way it was implemented at least.I'd prefer to do lot of editing as opposed to lot of reading through to not introduce silent semantical bugs - which is exactly how switching between struct and class looks now. This is a major benefit, not an issue.what I would consider convenient is to limit struct/class distinctionto polymorphism exclusively, with not extra implications. So that you can still can do `MyClass on_stack;` (any `MyClass` is treated as type of object) but passing it to function wouldn't compile unless `ref` is also used. So where it is allocated you'd have 'MyClass' and everywhere it is used you'd have 'ref MyClass'. There are a lot of consequences of this, such as: 1. Want to switch between a class and a struct? You've got lots of editing to do.2. You'd have to invent a way to do 'alias ref MyClass T;'No way. `typedef int* p_int_t` is one of worst popular C idioms in my opinion. Typing extra three letters is a very minor price for having a code which looks like what it does.3. ref has special semantics in D about being a non-escaping pointer. This means issues if you want a 'ref MyClass' field in a struct.MyClass* should also be applicable, I have only mentioned `ref` because non-escpaing is usually desired :) Btw implementation of DIP25 is heavily incomplete, I have never managed to make it work in any of practical attempts. There are quite some bug reports open : https://issues.dlang.org/buglist.cgi?quicksearch=dip25&list_id=207387I'm not saying your idea is necessarily bad, but there is a heckuva lot to think about in interactions with other features. It's not so easy to produce a design that doesn't have a nail sticking up here or there. I don't know of any language that succeeded in that.Well, languages that simply declare everything a reference (JS) or dropped support for inheritance based polymorphism (Go, Rust) are much more consistent in that regard in my opinion :) There isn't much point in discussin details at this point as the ship has long sailed. But I definitely consider this one of underdesigned parts of D language.
Mar 28 2016
On 3/28/2016 9:56 PM, Dicebot wrote:It is hard to argue that but I have never encountered any issues from actual confusion between struct and class in C++ (because there isn't any real difference), only from misusage of virtual types.Misusage of virtual types is the confusion.My experience is the opposite. I've found it quick & easy to attempt different data structures in D because of the minimal editing. In C++, I (and I suspect most people) just go with their first design because it is too much of a pain to edit all the usages. That is what I've dubbed "brittleness". One way I was able to quickly achieve speed in Warp was it was easy to try out different data structures. Much, much easier than in C++. The end result could be done in C++, but getting there would probably not have happened.1. Want to switch between a class and a struct? You've got lots of editing to do.I'd prefer to do lot of editing as opposed to lot of reading through to not introduce silent semantical bugs - which is exactly how switching between struct and class looks now. This is a major benefit, not an issue.You'd have to give up on writing generic code, then.2. You'd have to invent a way to do 'alias ref MyClass T;'No way. `typedef int* p_int_t` is one of worst popular C idioms in my opinion. Typing extra three letters is a very minor price for having a code which looks like what it does.Well, languages that simply declare everything a reference (JS) or dropped support for inheritance based polymorphism (Go, Rust) are much more consistent in that regard in my opinion :)JS and Go throw a lot of capability under the bus in order to achieve consistency. It's a high price. I don't know enough about Rust to say what their tradeoffs here really are.There isn't much point in discussin details at this point as the ship has long sailed. But I definitely consider this one of underdesigned parts of D language.True dat.
Mar 29 2016
Could anybody explain what this mean and why this way is not modern?This is in the context of users migrating from C++, and it is bad in so far as it is not what a C++ programmer who hasn't read all the documentation would expect. The easiest path of migration would be if the programmer can design a program the same way they would a C++ program but using D syntax. this, transitive const and I think thread local by default make migration in this way harder. (Though probably worth it in the long run)
Mar 29 2016