digitalmars.D - What would break if class was merged with struct
- Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= (9/9) May 27 2017 I wonder, what would break if all the features of class was
- Stanislav Blinov (11/20) May 27 2017 It's not "a little bit", it's ABI down the drain, along with a
- Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= (7/11) May 27 2017 Why would you loose interfaces and extern(C++)?
- Stanislav Blinov (9/17) May 27 2017 There's a lot more difference in D. Classes in D are fat memory
- Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= (8/15) May 27 2017 So are classes with virtual functions in C++, to get RTTI you
- Stanislav Blinov (14/30) May 27 2017 But structs in D have none of that.
- Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= (15/26) May 27 2017 Neither does C++ if you don't add a virtual function to it, so it
- Moritz Maxeiner (5/8) May 27 2017 Smart pointers impose a specific object lifetime, whereas (D)
- Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= (3/12) May 27 2017 In this context smart pointers are just pointers that aren't raw
- Moritz Maxeiner (6/20) May 27 2017 Then please don't call them "smart", because that term is
- Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= (6/10) May 27 2017 "smart pointer" just means that it is a pointer wrapped in an
- Moritz Maxeiner (7/17) May 27 2017 An ADT that adds features to the wrapped pointer; and if it adds
- Stanislav Blinov (3/12) May 27 2017 Lower? No. Wrap - yes. With "scope" from DIP1000 you can even do
- Moritz Maxeiner (9/23) May 27 2017 Maybe I was not clear: Of course you can put a class reference
- Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= (10/16) May 27 2017 I am not sure what you mean here. As long as the "smart pointer"
- Moritz Maxeiner (29/43) May 27 2017 An example, then:
- Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= (8/16) May 27 2017 Does the language spec say anything about the size of class
- Moritz Maxeiner (11/27) May 27 2017 Yes, is is defined as `ptrsize` and must have the exact same size
- Ola Fosheim Grostad (7/25) May 27 2017 Huh? You are talking about lambdas?
- Ola Fosheim Grostad (4/6) May 27 2017 Please note that an ABI is an implementation specific linkage
- Stanislav Blinov (14/42) May 27 2017 But they are incompatible precisely because structs "don't have
- Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= (8/20) May 27 2017 I don't understand this argument, why would this be more
- Stanislav Blinov (10/28) May 27 2017 Perhaps it wouldn't be if we were talking about new language.
- Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= (8/17) May 27 2017 No. I am talking about language semantics. Are the semantics for
- Stanislav Blinov (4/10) May 27 2017 Ahem. As specified, classes are reference types, struct aren't.
- Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= (2/15) May 27 2017 Structs are reference types too. The specification is wrong.
- Stanislav Blinov (9/27) May 27 2017 I've seen this argument from you before, and it's incorrect.
- Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= (14/21) May 27 2017 This is the ACID test: Values have no identity. An instance of a
- Iain Buclaw via Digitalmars-d (41/51) May 28 2017 The semantic difference is that structs are POD records, and classes
- Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= (11/29) May 28 2017 Yes, but you could do that for structs as well, after static
- Iain Buclaw via Digitalmars-d (12/38) May 28 2017 I said it all in one breath, so you could leave it up to
- Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= (13/25) May 28 2017 Well, class and struct is semantically the same in C++. The only
- Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= (4/7) May 28 2017 I.e. you can just search-and-replace "struct" with "class" in C++
- Jonathan M Davis via Digitalmars-d (17/19) May 27 2017 There was definitely talk of doing it, but it's never actually happened....
- Iain Buclaw via Digitalmars-d (4/15) May 28 2017 There's nothing blocking the deprecation of monitors. Just someone
- Iain Buclaw via Digitalmars-d (7/16) May 28 2017 Strictly speaking, this already is the case.
- Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= (7/12) May 28 2017 Right, but since the language now is more powerful than it was in
I wonder, what would break if all the features of class was merged into struct? Imagine that: class Something ... { ... } is lowered into: struct _class_Something ... { ... } alias Something = MagicClassRef!_class_Something; Is it conceivable with some language changes, a bit of automated source updating and a little bit of breakage?
May 27 2017
On Saturday, 27 May 2017 at 14:12:09 UTC, Ola Fosheim Grøstad wrote:I wonder, what would break if all the features of class was merged into struct? Imagine that: class Something ... { ... } is lowered into: struct _class_Something ... { ... } alias Something = MagicClassRef!_class_Something; Is it conceivable with some language changes, a bit of automated source updating and a little bit of breakage?It's not "a little bit", it's ABI down the drain, along with a good part of runtime. And we'd lose interfaces and extern(C++). That being said, it is totally possible today to have struct wrappers over classes, both malloc'ed and stack-allocated. The problem is that destruction is always system (due to reasons described in my "Destructor attribute inheritance" thread: http://forum.dlang.org/thread/wtxkfylodzaaifojaglr forum.dlang.org). And one has to adopt a discipline not to escape references. Once DIP1000 is fully realized, at least the latter part will become unnecessary.
May 27 2017
On Saturday, 27 May 2017 at 16:04:42 UTC, Stanislav Blinov wrote:It's not "a little bit", it's ABI down the drain, along with a good part of runtime. And we'd lose interfaces and extern(C++).Why would you loose interfaces and extern(C++)? "struct" and "class" are interchangeable keywords in C++ (only affects encapsulation). So not a lot more difference than POD vs non-POD in C++?That being said, it is totally possible today to have struct wrappers over classes, both malloc'ed and stack-allocated.Well, I am asking more out of a theoretical interest for what the core language in D could boil down to.
May 27 2017
On Saturday, 27 May 2017 at 16:23:33 UTC, Ola Fosheim Grøstad wrote:On Saturday, 27 May 2017 at 16:04:42 UTC, Stanislav Blinov wrote:There's a lot more difference in D. Classes in D are fat memory chunks storing pointers to ClassInfo (inc. vtable), Monitor (i.e. for "synchronized") and a list of all interfaces they implement, that's before we get to data members. If we were to remove all that, we'd lose the semi-natural way of interfacing to C++ classes, and some pretty horrendous code involving void* and void** would have to be used.It's not "a little bit", it's ABI down the drain, along with a good part of runtime. And we'd lose interfaces and extern(C++).Why would you loose interfaces and extern(C++)? "struct" and "class" are interchangeable keywords in C++ (only affects encapsulation). So not a lot more difference than POD vs non-POD in C++?
May 27 2017
On Saturday, 27 May 2017 at 16:31:32 UTC, Stanislav Blinov wrote:There's a lot more difference in D. Classes in D are fat memory chunks storing pointers to ClassInfo (inc. vtable),So are classes with virtual functions in C++, to get RTTI you need to have a virtual member function. I don't see the big difference.Monitor (i.e. for "synchronized") andWasn't this going to be removed?a list of all interfaces they implement,Semantically roughly the same as multiple-inheritance in C++ but more limited.If we were to remove all that, we'd lose the semi-natural way of interfacing to C++ classes, and some pretty horrendous code involving void* and void** would have to be used.I don't understand what you mean here.
May 27 2017
On Saturday, 27 May 2017 at 16:37:04 UTC, Ola Fosheim Grøstad wrote:On Saturday, 27 May 2017 at 16:31:32 UTC, Stanislav Blinov wrote:But structs in D have none of that.There's a lot more difference in D. Classes in D are fat memory chunks storing pointers to ClassInfo (inc. vtable),So are classes with virtual functions in C++, to get RTTI you need to have a virtual member function. I don't see the big difference.Not that I'm aware of.Monitor (i.e. for "synchronized") andWasn't this going to be removed?If your "struct _class_SomeThing" would simply describe the same memory layout of classes that we have today, then no language change is necessary, it's purely a library solution. Well... maybe we'd need to add class postblits if we wanted copying (which can also be done by hand with a library "clone" function and a "special" static __postblit function). If not, then it gets complicated, as in order to retain an interface with C++ classes, D would either have to follow C++ ABI (he-he), or at the very least put the burden of mapping member function calls on the programmer.a list of all interfaces they implement,Semantically roughly the same as multiple-inheritance in C++ but more limited.If we were to remove all that, we'd lose the semi-natural way of interfacing to C++ classes, and some pretty horrendous code involving void* and void** would have to be used.I don't understand what you mean here.
May 27 2017
On Saturday, 27 May 2017 at 16:52:17 UTC, Stanislav Blinov wrote:But structs in D have none of that.Neither does C++ if you don't add a virtual function to it, so it would be the same. My question isn't whether structs have it now, but if the concept struct and class could be merged. Basically, the question is: are there features that are incompatible in terms of semantics? The class reference type should be fixable with a rewrite into templated smart pointers, so no need for big changes there, I think. The "new" construct would have to change a little bit so that it instantiates the pointed-to-type and not the reference-type.If your "struct _class_SomeThing" would simply describe the same memory layout of classes that we have today, then no language change is necessary, it's purely a library solution. Well... maybe we'd need to add class postblits if we wanted copying (which can also be done by hand with a library "clone" function and a "special" static __postblit function).Sure, D tries to stay compatible with C++, so that would dictate the memory layout.If not, then it gets complicated, as in order to retain an interface with C++ classes, D would either have to follow C++ ABI (he-he), or at the very least put the burden of mapping member function calls on the programmer.I thought D matched up to C++ ABI for structs/classes already (gdc vs g++, ldc vs clang)?
May 27 2017
On Saturday, 27 May 2017 at 17:02:40 UTC, Ola Fosheim Grøstad wrote:The class reference type should be fixable with a rewrite into templated smart pointers, so no need for big changes there, I think.Smart pointers impose a specific object lifetime, whereas (D) classes do not. You cannot lower (D) class instances to smart pointers.
May 27 2017
On Saturday, 27 May 2017 at 17:19:48 UTC, Moritz Maxeiner wrote:On Saturday, 27 May 2017 at 17:02:40 UTC, Ola Fosheim Grøstad wrote:In this context smart pointers are just pointers that aren't raw pointers, e.g. alias this or something.The class reference type should be fixable with a rewrite into templated smart pointers, so no need for big changes there, I think.Smart pointers impose a specific object lifetime, whereas (D) classes do not. You cannot lower (D) class instances to smart pointers.
May 27 2017
On Saturday, 27 May 2017 at 17:24:14 UTC, Ola Fosheim Grøstad wrote:On Saturday, 27 May 2017 at 17:19:48 UTC, Moritz Maxeiner wrote:Then please don't call them "smart", because that term is specifically reserved for something that adds at least some additional features over a regular pointer (bounds checking, memory / lifetime management, etc.).On Saturday, 27 May 2017 at 17:02:40 UTC, Ola Fosheim Grøstad wrote:In this context smart pointers are just pointers that aren't raw pointers, e.g. alias this or something.The class reference type should be fixable with a rewrite into templated smart pointers, so no need for big changes there, I think.Smart pointers impose a specific object lifetime, whereas (D) classes do not. You cannot lower (D) class instances to smart pointers.
May 27 2017
On Saturday, 27 May 2017 at 18:21:41 UTC, Moritz Maxeiner wrote:Then please don't call them "smart", because that term is specifically reserved for something that adds at least some additional features over a regular pointer (bounds checking, memory / lifetime management, etc.)."smart pointer" just means that it is a pointer wrapped in an ADT. In this context it could provide allocation-information would be one thing it could provide, or reference counting, member access or whatever. The "smart" part was deliberately left unspecified.
May 27 2017
On Saturday, 27 May 2017 at 18:33:36 UTC, Ola Fosheim Grøstad wrote:On Saturday, 27 May 2017 at 18:21:41 UTC, Moritz Maxeiner wrote:An ADT that adds features to the wrapped pointer; and if it adds features, it is not *just* a normal pointer anymore, i.e. you cannot use it as a verbatim replacement for normal class instances on the language level, because you change their semantics.Then please don't call them "smart", because that term is specifically reserved for something that adds at least some additional features over a regular pointer (bounds checking, memory / lifetime management, etc.)."smart pointer" just means that it is a pointer wrapped in an ADT. In this context it could provide allocation-information would be one thing it could provide, or reference counting, member access or whatever. The "smart" part was deliberately left unspecified.
May 27 2017
On Saturday, 27 May 2017 at 17:19:48 UTC, Moritz Maxeiner wrote:On Saturday, 27 May 2017 at 17:02:40 UTC, Ola Fosheim Grøstad wrote:Lower? No. Wrap - yes. With "scope" from DIP1000 you can even do it in a safe manner.The class reference type should be fixable with a rewrite into templated smart pointers, so no need for big changes there, I think.Smart pointers impose a specific object lifetime, whereas (D) classes do not. You cannot lower (D) class instances to smart pointers.
May 27 2017
On Saturday, 27 May 2017 at 17:28:47 UTC, Stanislav Blinov wrote:On Saturday, 27 May 2017 at 17:19:48 UTC, Moritz Maxeiner wrote:Maybe I was not clear: Of course you can put a class reference inside a struct, or even simulate a class using a rewriting mechanism, but you *cannot* use a smart pointer as a replacement for a class instance, because the latter is normal pointer, and the former adds features on top of a pointer; they cannot be the same as a matter of definition, i.e. you cannot replace classes with smart pointer structs on the language level, because it removes features from the language.On Saturday, 27 May 2017 at 17:02:40 UTC, Ola Fosheim Grøstad wrote:Lower? No. Wrap - yes. With "scope" from DIP1000 you can even do it in a safe manner.The class reference type should be fixable with a rewrite into templated smart pointers, so no need for big changes there, I think.Smart pointers impose a specific object lifetime, whereas (D) classes do not. You cannot lower (D) class instances to smart pointers.
May 27 2017
On Saturday, 27 May 2017 at 18:26:07 UTC, Moritz Maxeiner wrote:mechanism, but you *cannot* use a smart pointer as a replacement for a class instance, because the latter is normal pointer, and the former adds features on top of a pointer; they cannot be the same as a matter of definition, i.e. you cannot replace classes with smart pointer structs on the language level, because it removes features from the language.I am not sure what you mean here. As long as the "smart pointer" is in a subtype relationship with the current "class reference" then it can add features, yes? You could do this as a compiler configuration even, switch out GC with ref-counting smart pointers. The point of this thread was to have fewer language constructs, with more lowering, so that the resulting language would be a super-language, that fully covers the original language (or close to it).
May 27 2017
On Saturday, 27 May 2017 at 18:42:02 UTC, Ola Fosheim Grøstad wrote:On Saturday, 27 May 2017 at 18:26:07 UTC, Moritz Maxeiner wrote:An example, then: --- module a; class Foo {} module b; import a; void bar(Foo foo) {} --- Here, `bar`, takes a (pointer to a) class instance as parameter `foo`. `foo` is a single pointer, i.e. 8 bytes on a 64bit OS, with *no* special semantics. You cannot replace the meaning of type `Foo` here with something that is not also exactly 8 bytes (on 64bit OS) with no special semantics, because that changes the semantics of `bar`. i.e. `Foo` must not be a smart pointer because a smart pointer necessarily introduces features (and thus changes the semantics). And this is exactly what you were proposing in the sentence I replied to; you were proposing to essentially change the semantics of every use of a class instance in all D code by rewriting `Foo` into a smart pointer.mechanism, but you *cannot* use a smart pointer as a replacement for a class instance, because the latter is normal pointer, and the former adds features on top of a pointer; they cannot be the same as a matter of definition, i.e. you cannot replace classes with smart pointer structs on the language level, because it removes features from the language.I am not sure what you mean here. As long as the "smart pointer" is in a subtype relationship with the current "class reference" then it can add features, yes?The point of this thread was to have fewer language constructs,And my reply was "if you want to do this, it must use a normal pointer, not a smart pointer, because that changes semantics". If you want a smart pointer, use one, but don't suddenly make something that isn't a smart pointer by language design change shape into a smart pointer.with more lowering, so that the resulting language would be a super-language, that fully covers the original language (or close to it).Sure, but then type `Foo` in the above must remain a normal pointer, not become a smart pointer.
May 27 2017
On Saturday, 27 May 2017 at 19:01:12 UTC, Moritz Maxeiner wrote:Here, `bar`, takes a (pointer to a) class instance as parameter `foo`. `foo` is a single pointer, i.e. 8 bytes on a 64bit OS, with *no* special semantics.Does the language spec say anything about the size of class references?If you want a smart pointer, use one, but don't suddenly make something that isn't a smart pointer by language design change shape into a smart pointer.Is it specified? The common implementation uses a GC, but does it say that an implementation cannot use a reference counted smart pointer or a fat pointer instead?Sure, but then type `Foo` in the above must remain a normal pointer, not become a smart pointer.That really depends on the definition of the language.
May 27 2017
On Saturday, 27 May 2017 at 19:26:50 UTC, Ola Fosheim Grøstad wrote:On Saturday, 27 May 2017 at 19:01:12 UTC, Moritz Maxeiner wrote:Yes, is is defined as `ptrsize` and must have the exact same size as a pointer to a struct and - more importantly - a pointer to a stack frame[1].Here, `bar`, takes a (pointer to a) class instance as parameter `foo`. `foo` is a single pointer, i.e. 8 bytes on a 64bit OS, with *no* special semantics.Does the language spec say anything about the size of class references?Yes, see above link. Unless you make *all* stack frame pointers smart pointers (which makes no sense whatsoever), class instances cannot be smart pointers in the language as it is specified right now.If you want a smart pointer, use one, but don't suddenly make something that isn't a smart pointer by language design change shape into a smart pointer.Is it specified?The common implementation uses a GC, but does it say that an implementation cannot use a reference counted smart pointer or a fat pointer instead?Sure, and the definition requires it. [1] https://dlang.org/spec/abi.html#delegatesSure, but then type `Foo` in the above must remain a normal pointer, not become a smart pointer.That really depends on the definition of the language.
May 27 2017
On Saturday, 27 May 2017 at 20:24:26 UTC, Moritz Maxeiner wrote:On Saturday, 27 May 2017 at 19:26:50 UTC, Ola Fosheim Grøstad wrote:Huh? You are talking about lambdas? Didnt find anything on class references in that Intel specific ABI, which appears to be optional anyway.On Saturday, 27 May 2017 at 19:01:12 UTC, Moritz Maxeiner wrote:Yes, is is defined as `ptrsize` and must have the exact same size as a pointer to a struct and - more importantly - a pointer to a stack frame[1].Here, `bar`, takes a (pointer to a) class instance as parameter `foo`. `foo` is a single pointer, i.e. 8 bytes on a 64bit OS, with *no* special semantics.Does the language spec say anything about the size of class references?Yes, see above link. Unless you make *all* stack frame pointers smart pointers (which makes no sense whatsoever), class instances cannot be smart pointers in the language as it is specified right now.I don't understand. Why are frame pointers relevant for class references?Sure, and the definition requires it.Why?
May 27 2017
On Saturday, 27 May 2017 at 20:24:26 UTC, Moritz Maxeiner wrote:Sure, and the definition requires it. [1] https://dlang.org/spec/abi.html#delegatesPlease note that an ABI is an implementation specific linkage detail, it cannot be portable so it does not define language semantics.
May 27 2017
On Saturday, 27 May 2017 at 17:02:40 UTC, Ola Fosheim Grøstad wrote:On Saturday, 27 May 2017 at 16:52:17 UTC, Stanislav Blinov wrote:But they are incompatible precisely because structs "don't have it". Inheritance for one. Reference semantics for another. A class reference is a pointer in disguise, struct is full layout on the stack. The only way to retain inheritance and reference semantics while removing "class" keyword would be not to merge classes into structs, but structs into classes. And then what, always allocate on the heap?But structs in D have none of that.Neither does C++ if you don't add a virtual function to it, so it would be the same. My question isn't whether structs have it now, but if the concept struct and class could be merged. Basically, the question is: are there features that are incompatible in terms of semantics?The class reference type should be fixable with a rewrite into templated smart pointers, so no need for big changes there, I think. The "new" construct would have to change a little bit so that it instantiates the pointed-to-type and not the reference-type.Which is all possible as a library with zero language changes. But for that to work, classes shall remain classes and structs shall remain structs.If that were true, we wouldn't even need the "extern(C++)", would we?If your "struct _class_SomeThing" would simply describe the same memory layout of classes that we have today, then no language change is necessary, it's purely a library solution. Well... maybe we'd need to add class postblits if we wanted copying (which can also be done by hand with a library "clone" function and a "special" static __postblit function).Sure, D tries to stay compatible with C++, so that would dictate the memory layout.If not, then it gets complicated, as in order to retain an interface with C++ classes, D would either have to follow C++ ABI (he-he), or at the very least put the burden of mapping member function calls on the programmer.I thought D matched up to C++ ABI for structs/classes already (gdc vs g++, ldc vs clang)?
May 27 2017
On Saturday, 27 May 2017 at 17:22:02 UTC, Stanislav Blinov wrote:But they are incompatible precisely because structs "don't have it". Inheritance for one. Reference semantics for another. A class reference is a pointer in disguise, struct is full layout on the stack. The only way to retain inheritance and reference semantics while removing "class" keyword would be not to merge classes into structs, but structs into classes. And then what, always allocate on the heap?I don't understand this argument, why would this be more difficult for D than C++? You lower class into struct (with virtual, interfaces, whistles and bells) and retain reference semantics by making it unavailable for D-move-semantics.Which is all possible as a library with zero language changes. But for that to work, classes shall remain classes and structs shall remain structs.Huh?If that were true, we wouldn't even need the "extern(C++)", would we?Sounds more like an implementation detail to me.
May 27 2017
On Saturday, 27 May 2017 at 17:30:49 UTC, Ola Fosheim Grøstad wrote:On Saturday, 27 May 2017 at 17:22:02 UTC, Stanislav Blinov wrote:Perhaps it wouldn't be if we were talking about new language. With D, such a change falls out of "some language changes, a bit of automated source updating and a little bit of breakage", and becomes "whole language change, a rewrite of runtime and standard library, and breaking every single project that uses D today". Or did we leave behind your original question?But they are incompatible precisely because structs "don't have it". Inheritance for one. Reference semantics for another. A class reference is a pointer in disguise, struct is full layout on the stack. The only way to retain inheritance and reference semantics while removing "class" keyword would be not to merge classes into structs, but structs into classes. And then what, always allocate on the heap?I don't understand this argument, why would this be more difficult for D than C++?Yes.Which is all possible as a library with zero language changes. But for that to work, classes shall remain classes and structs shall remain structs.Huh?:) Everything is an "implementation detail".If that were true, we wouldn't even need the "extern(C++)", would we?Sounds more like an implementation detail to me.
May 27 2017
On Saturday, 27 May 2017 at 18:06:11 UTC, Stanislav Blinov wrote:Perhaps it wouldn't be if we were talking about new language. With D, such a change falls out of "some language changes, a bit of automated source updating and a little bit of breakage", and becomes "whole language change, a rewrite of runtime and standard library, and breaking every single project that uses D today". Or did we leave behind your original question?No. I am talking about language semantics. Are the semantics for class and struct conflicting or can they be merged? That is the question. I am talking about the language, as specified, not the implementation.Yes.Huhhh?? :^):) Everything is an "implementation detail".No... No... No...
May 27 2017
On Saturday, 27 May 2017 at 18:13:52 UTC, Ola Fosheim Grøstad wrote:Ahem. As specified, classes are reference types, struct aren't. What more is there to say?Or did we leave behind your original question?No. I am talking about language semantics. Are the semantics for class and struct conflicting or can they be merged? That is the question. I am talking about the language, as specified, not the implementation.
May 27 2017
On Saturday, 27 May 2017 at 18:44:03 UTC, Stanislav Blinov wrote:On Saturday, 27 May 2017 at 18:13:52 UTC, Ola Fosheim Grøstad wrote:Structs are reference types too. The specification is wrong.Ahem. As specified, classes are reference types, struct aren't. What more is there to say?Or did we leave behind your original question?No. I am talking about language semantics. Are the semantics for class and struct conflicting or can they be merged? That is the question. I am talking about the language, as specified, not the implementation.
May 27 2017
On Saturday, 27 May 2017 at 18:44:42 UTC, Ola Fosheim Grøstad wrote:On Saturday, 27 May 2017 at 18:44:03 UTC, Stanislav Blinov wrote:I've seen this argument from you before, and it's incorrect. Structs may adopt reference semantics if they aggregate pointers, that's true. But they are not themselves reference types. Their representation is laid out inline. Classes, OTOH, are always references, to get at their memory you need an indirection. Thus, if we were to merge classes and structs, we'd have to pick one or the other.On Saturday, 27 May 2017 at 18:13:52 UTC, Ola Fosheim Grøstad wrote:Structs are reference types too. The specification is wrong.Ahem. As specified, classes are reference types, struct aren't. What more is there to say?Or did we leave behind your original question?No. I am talking about language semantics. Are the semantics for class and struct conflicting or can they be merged? That is the question. I am talking about the language, as specified, not the implementation.
May 27 2017
On Saturday, 27 May 2017 at 18:56:47 UTC, Stanislav Blinov wrote:I've seen this argument from you before, and it's incorrect. Structs may adopt reference semantics if they aggregate pointers, that's true. But they are not themselves reference types. Their representation is laid out inline.This is the ACID test: Values have no identity. An instance of a struct has an identity. Allocation is another issue. A stack allocation is just an optimization of a heap allocation. Many languages put all the activation records (stack frames) on the heap. This is very useful for high levels of concurrency.Classes, OTOH, are always references, to get at their memory you need an indirection. Thus, if we were to merge classes and structs, we'd have to pick one or the other.Structs are more general, so you don't have to pick anything, you just add the class features to the struct. That means the minimal core language no longer have the class concept. The full language with lowering (syntactical sugar) still has the class concept since it can be covered by struct + "smart pointer" + modified new.
May 27 2017
On 27 May 2017 at 20:13, Ola Fosheim Grøstad via Digitalmars-d <digitalmars-d puremagic.com> wrote:On Saturday, 27 May 2017 at 18:06:11 UTC, Stanislav Blinov wrote:The semantic difference is that structs are POD records, and classes are references (or pointers) to GC heap with inheritance (underlying record includes fields from base classes). For ABI, structs are compatible with C (this is documented as per spec), and classes underlying records are compatible with C++ (don't think this is documented, but it's certainly assumed). Focusing on the latter point, this means that the following declarations: struct Something { int a; long b; char c; } class Something { int a; long b; char c; } are identical to each other, apart from the latter getting a __vptr and __monitor field. However, for extern(D) classes, there's actually nothing stopping a D compiler implementer from making class types more memory efficient, an optimizing compiler could decide to re-arrange class fields as: class Something { long b; int a; char c; } After all, we only need extern(D) to be compatible with ourselves, not other languages. As a side note, when I talked about D at the GNU Hackers Meeting a number of years back, when I said that structs and classes are two distinct types - one being POD-only, the other being a reference that comes with the bells and whistles of OOP - I actually got a small cheer. This gives me a very strong impression of what C++ programmers think of their own situation regarding struct vs class, and that we should not be so eager to follow their design.Perhaps it wouldn't be if we were talking about new language. With D, such a change falls out of "some language changes, a bit of automated source updating and a little bit of breakage", and becomes "whole language change, a rewrite of runtime and standard library, and breaking every single project that uses D today". Or did we leave behind your original question?No. I am talking about language semantics. Are the semantics for class and struct conflicting or can they be merged?
May 28 2017
On Sunday, 28 May 2017 at 09:09:39 UTC, Iain Buclaw wrote:However, for extern(D) classes, there's actually nothing stopping a D compiler implementer from making class types more memory efficient, an optimizing compiler could decide to re-arrange class fields as: class Something { long b; int a; char c; }Yes, but you could do that for structs as well, after static analysis establishing that it no code in this specific program is making assumptions about layout. Or you could have an attribute that says that that field X should be at byte-offset N, but all other fields can move.As a side note, when I talked about D at the GNU Hackers Meeting a number of years back, when I said that structs and classes are two distinct types - one being POD-only, the other being a reference that comes with the bells and whistles of OOP - I actually got a small cheer. This gives me a very strong impression of what C++ programmers think of their own situation regarding struct vs class, and that we should not be so eager to follow their design.Did they explain why? Many other languages provide a single construct with far more wide-ranging features than D/C++. For generic programming it is generally better to have fewer constructs, but you might need a way convenient way to express constraints (i.e. C++ concepts).
May 28 2017
On 28 May 2017 at 13:30, Ola Fosheim Grøstad via Digitalmars-d <digitalmars-d puremagic.com> wrote:On Sunday, 28 May 2017 at 09:09:39 UTC, Iain Buclaw wrote:I said it all in one breath, so you could leave it up to interpretation whether they applauded the fact that there is a separation in semantics, or whether there is no multiple inheritance in D (except via interfaces). When asking one person over dinner later about what they felt was wrong about struct/class in C++, I got the impression that because there's almost no distinction between the two, class seems more like a misfeature of C++. You could say that C++ should have stuck to one type, instead of having two. And because in D we make a very clear distinction, that justifies the reason to have both struct and class.However, for extern(D) classes, there's actually nothing stopping a D compiler implementer from making class types more memory efficient, an optimizing compiler could decide to re-arrange class fields as: class Something { long b; int a; char c; }Yes, but you could do that for structs as well, after static analysis establishing that it no code in this specific program is making assumptions about layout. Or you could have an attribute that says that that field X should be at byte-offset N, but all other fields can move.As a side note, when I talked about D at the GNU Hackers Meeting a number of years back, when I said that structs and classes are two distinct types - one being POD-only, the other being a reference that comes with the bells and whistles of OOP - I actually got a small cheer. This gives me a very strong impression of what C++ programmers think of their own situation regarding struct vs class, and that we should not be so eager to follow their design.Did they explain why? Many other languages provide a single construct with far more wide-ranging features than D/C++.
May 28 2017
On Sunday, 28 May 2017 at 12:31:35 UTC, Iain Buclaw wrote:I said it all in one breath, so you could leave it up to interpretation whether they applauded the fact that there is a separation in semantics, or whether there is no multiple inheritance in D (except via interfaces). When asking one person over dinner later about what they felt was wrong about struct/class in C++, I got the impression that because there's almost no distinction between the two, class seems more like a misfeature of C++.Well, class and struct is semantically the same in C++. The only difference is that you don't have private and protected on structs. So the distinction is historical, to quote cppreference.com: «The keywords are identical except for the default member access and the default base class access.»You could say that C++ should have stuck to one type, instead of having two.Struct and class is one type in C++. The difference is in the syntax where the grammar does not allow access protection for the struct keyword. So not semantical, but syntactical.And because in D we make a very clear distinction, that justifies the reason to have both struct and class.But you don't make a very clear distinction in D. If struct was a pure value type and mapped to pure valued tuples, then you might have a justification for it. From a type-system point of view the distinction makes no sense to me.
May 28 2017
On Sunday, 28 May 2017 at 14:30:00 UTC, Ola Fosheim Grøstad wrote:Struct and class is one type in C++. The difference is in the syntax where the grammar does not allow access protection for the struct keyword. So not semantical, but syntactical.I.e. you can just search-and-replace "struct" with "class" in C++ and it will behave the same way. "struct" is only used as a mnemonic device...
May 28 2017
On Saturday, May 27, 2017 16:37:04 Ola Fosheim Grøstad via Digitalmars-d wrote:There was definitely talk of doing it, but it's never actually happened. I don't think that it was actually decided that we would though, and some other things that we _definitely_ decided we do have never actually happened either (e.g. remove delete from the language and remove toString, toHash, opCmp, and opEquals from Object). Getting major changes in is often something that doesn't work out very well given the obstacles involved. I don't recall what the obstacles to getting the monitor changes in where, but I suspect that in order to get them in, someone would effectively have to champion the changes and push them through, and while I think that there was someone trying to do that at one point, they seem to have given up on it. I don't know if they ran into insurmountable problems or simply gave up and left. But as long as D classes have a built-in monitor, then that's one of the key differences between a D class or struct (or a D and C++ class for that matter). - Jonathan M DavisMonitor (i.e. for "synchronized") andWasn't this going to be removed?
May 27 2017
On 27 May 2017 at 20:34, Jonathan M Davis via Digitalmars-d <digitalmars-d puremagic.com> wrote:On Saturday, May 27, 2017 16:37:04 Ola Fosheim Grøstad via Digitalmars-d wrote:There's nothing blocking the deprecation of monitors. Just someone needs to do the work.There was definitely talk of doing it, but it's never actually happened. I don't think that it was actually decided that we would though, and some other things that we _definitely_ decided we do have never actually happened either (e.g. remove delete from the language and remove toString, toHash, opCmp, and opEquals from Object). Getting major changes in is often something that doesn't work out very well given the obstacles involved.Monitor (i.e. for "synchronized") andWasn't this going to be removed?
May 28 2017
On 27 May 2017 at 16:12, Ola Fosheim Grøstad via Digitalmars-d <digitalmars-d puremagic.com> wrote:I wonder, what would break if all the features of class was merged into struct? Imagine that: class Something ... { ... } is lowered into: struct _class_Something ... { ... } alias Something = MagicClassRef!_class_Something; Is it conceivable with some language changes, a bit of automated source updating and a little bit of breakage?Strictly speaking, this already is the case. Something sth = new Something (...); all that is really doing is just: struct Something* sth = new Something (...); You just aren't exposed this in the language.
May 28 2017
On Sunday, 28 May 2017 at 08:24:50 UTC, Iain Buclaw wrote:Strictly speaking, this already is the case. Something sth = new Something (...); all that is really doing is just: struct Something* sth = new Something (...); You just aren't exposed this in the language.Right, but since the language now is more powerful than it was in D1, it should be possible to implement class references as a templated struct, right? So there is no longer a need for this special casing of class vs struct. The only thing you need to do is modify "new" to recognize it. I think?
May 28 2017