digitalmars.D - Non-transitive immutable? Read only struct.
- Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= (16/16) Dec 05 2019 So, I get it, head-const has been discussed to death before. But
- Gregor =?UTF-8?B?TcO8Y2ts?= (7/24) Dec 06 2019 Can you clarify how this goes beyond the classic OO pattern of
- Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= (10/15) Dec 06 2019 You cannot easily emulate it since this is low-level typing where
- Simen =?UTF-8?B?S2rDpnLDpXM=?= (17/26) Dec 06 2019 immutable fields can be initialized in constructors. Getters
- Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= (22/46) Dec 06 2019 But immutable fields cannot contain pointers to non-immutable
- Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= (4/17) Dec 06 2019 I guess you could use const for ROM, but that might affect
- Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= (8/8) Dec 06 2019 I guess I should have stated more clearly to major optimization
So, I get it, head-const has been discussed to death before. But it seems to me that it is more of a problem that there is no (to my awareness) non-transitive immutable. If there is, I apologize. So, there are at least 4 situations where you really want that: 1. Protect fields in structs/classes after initialization. Reduces bugs. Documents intent. 2. Turn received values from functions into something that cannot be modified reliably irrespective of what the protection the called function has set for it. Reduces bugs. 3. To have sensible immutable tuples that can point to non-immutable things. In my view, a must have. 4. To have structures in ROM that can point to memory mapped registers or RAM. Not a must have, but sensible. I'm not saying that immutable should change, but that there is need for something in addition to that. Call it "readonly" if you want.
Dec 05 2019
On Thursday, 5 December 2019 at 17:01:07 UTC, Ola Fosheim Grøstad wrote:So, I get it, head-const has been discussed to death before. But it seems to me that it is more of a problem that there is no (to my awareness) non-transitive immutable. If there is, I apologize. So, there are at least 4 situations where you really want that: 1. Protect fields in structs/classes after initialization. Reduces bugs. Documents intent. 2. Turn received values from functions into something that cannot be modified reliably irrespective of what the protection the called function has set for it. Reduces bugs. 3. To have sensible immutable tuples that can point to non-immutable things. In my view, a must have. 4. To have structures in ROM that can point to memory mapped registers or RAM. Not a must have, but sensible. I'm not saying that immutable should change, but that there is need for something in addition to that. Call it "readonly" if you want.Can you clarify how this goes beyond the classic OO pattern of private member variables with public getters and no setters? If there was a class-private visibility, D could emulate everything except point 3 on your list, I think, albeit somewhat verbosely. So how is your thinking diverging from that?
Dec 06 2019
On Friday, 6 December 2019 at 08:45:15 UTC, Gregor Mückl wrote:Can you clarify how this goes beyond the classic OO pattern of private member variables with public getters and no setters? If there was a class-private visibility, D could emulate everything except point 3 on your list, I think, albeit somewhat verbosely. So how is your thinking diverging from that?You cannot easily emulate it since this is low-level typing where you can obtain the address of the memory and that memory should be read only within its lifetime. The problem with "immutable" is that it requires that read only memory only can point to read only memory, which is too limiting. (You can try to set up a big machinery of emulating pointers etc, but then you are basically implementing a new type system within the type system. Which probably will be too cumbersome and therefore not used.)
Dec 06 2019
On Thursday, 5 December 2019 at 17:01:07 UTC, Ola Fosheim Grøstad wrote:1. Protect fields in structs/classes after initialization. Reduces bugs. Documents intent.immutable fields can be initialized in constructors. Getters allow you to define an interface that doesn't allow modification by outside forces while still allowing the class/struct to modify the fields if it feels like it, allowing both non-reassignable fields and lazy initialization.2. Turn received values from functions into something that cannot be modified reliably irrespective of what the protection the called function has set for it. Reduces bugs.Const does this. If you know it's immutable call assumeUnique on it. If you want to limit modification in some ways while allowing it in other ways, that sounds like a library thing, not something the language should do for you.3. To have sensible immutable tuples that can point to non-immutable things. In my view, a must have.Getters can be used for this.4. To have structures in ROM that can point to memory mapped registers or RAM. Not a must have, but sensible.Getters can do this. You'll probably have to dip into some un- safe code, but this seems like an exotic enough use case that we can live with that. -- Simen
Dec 06 2019
On Friday, 6 December 2019 at 09:11:11 UTC, Simen Kjærås wrote:On Thursday, 5 December 2019 at 17:01:07 UTC, Ola Fosheim Grøstad wrote:But immutable fields cannot contain pointers to non-immutable memory?1. Protect fields in structs/classes after initialization. Reduces bugs. Documents intent.immutable fields can be initialized in constructors.Getters allow you to define an interface that doesn't allow modification by outside forces while still allowing the class/struct to modify the fields if it feels like it, allowing both non-reassignable fields and lazy initialization.Making fields/attributes read only is not only for the external interface it is also documentation for internal use, to prevent accidental modification in the implementation, prevent inheritance issues, enables caching based on typing in generic programming.No, const does not do it. If you receive a mutable value it will be const, not immutable. If you use immutable it will fail if the value contains an immutable pointer. (I am not talking about returned references, but value copies) So there is no easy way to write this kind of code that has increased robustness in evolving codebases.2. Turn received values from functions into something that cannot be modified reliably irrespective of what the protection the called function has set for it. Reduces bugs.Const does this. If you know it's immutable call assumeUnique on it. If you want to limit modification in some ways while allowing it in other ways, that sounds like a library thing, not something the language should do for you.That does not make the memory immutable as seen from the compiler?3. To have sensible immutable tuples that can point to non-immutable things. In my view, a must have.Getters can be used for this.Casting away immutable sounds very dangerous. If that can be done then the optimizer cannot use immutable for anything? Anyway, getters are not useful in low level programming. You need to be able to take the address of the memory. So what you are left with is to leave it mutable to the typesystem and never write to it in your code, so basically no help from the type system.4. To have structures in ROM that can point to memory mapped registers or RAM. Not a must have, but sensible.Getters can do this. You'll probably have to dip into some un- safe code, but this seems like an exotic enough use case that we can live with that.
Dec 06 2019
On Friday, 6 December 2019 at 09:26:40 UTC, Ola Fosheim Grøstad wrote:I guess you could use const for ROM, but that might affect caching and ROM can be slow.Casting away immutable sounds very dangerous. If that can be done then the optimizer cannot use immutable for anything? Anyway, getters are not useful in low level programming. You need to be able to take the address of the memory. So what you are left with is to leave it mutable to the typesystem and never write to it in your code, so basically no help from the type system.4. To have structures in ROM that can point to memory mapped registers or RAM. Not a must have, but sensible.Getters can do this. You'll probably have to dip into some un- safe code, but this seems like an exotic enough use case that we can live with that.
Dec 06 2019
I guess I should have stated more clearly to major optimization advantages of having more memory set as immutable: 1. It allows the compiler to assume that there is no aliasing. 2. It allows the compiler to retain loaded values (registers/stack) even accross invalidation/barriers. 3. It allows generic code to retain cached copies of values/pointers obtained through a chain of immutable. Including pointers to mutable memory.
Dec 06 2019