www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - A small const problem

reply "bearophile" <bearophileHUGS lycos.com> writes:
In my code I have seen that in some situations I'd like to do
something with structs that const doesn't allow me to do. There
are many different cases of such usage, the following isn't my
most common example, but it shows better what I mean:


import std.random: randomShuffle;
struct Foo {
       const int x, y;
}
void main() {
       auto foos = [Foo(1,2), Foo(3,4)];
       randomShuffle(foos);
}


Here the Foo struct has two fields, they are tagged with const
because no method of Foo is ever allowed to change their value
once a Foo is built, and no one outside of Foo is allowed to
change them. So they are quite constant.

On the other hand if I have two or more Foos I sometimes want to
rebind an old Foo with a new one (a simple variable assign), or
in this program I even want to shuffle them. Shuffling them
doesn't change the logically constant nature of their x and y
fields.

So in a way here I am looking for a const that makes the struct
fields not mutable, but allows me to rebind the whole structs.

Currently std.typecons.rebindable works only on class instances,
interfaces and arrays (std.typecons.rebindable seems to accept
fixed-sized arrays too, but I don't know if this meaningful &
good). So it's not a solution.

I think the small problem shown here is not the logical const
needed for storing things like lazily computed hash values for
immutable structs. Here nothing inside Foo is allowed to change
once Foo is created (here I have not added mutable fields to Foo).

In such situations I sometimes don't use const, or sometimes I
use class instances, or even pointers.

Bye,
bearophile
Mar 15 2012
next sibling parent Jose Armando Garcia <jsancio gmail.com> writes:
On Thu, Mar 15, 2012 at 6:43 PM, bearophile <bearophileHUGS lycos.com> wrot=
e:
 In my code I have seen that in some situations I'd like to do
 something with structs that const doesn't allow me to do. There
 are many different cases of such usage, the following isn't my
 most common example, but it shows better what I mean:


 import std.random: randomShuffle;
 struct Foo {
 =A0 =A0 =A0const int x, y;
 }
 void main() {
 =A0 =A0 =A0auto foos =3D [Foo(1,2), Foo(3,4)];
 =A0 =A0 =A0randomShuffle(foos);
 }

Maybe in this particular case what you really want to do is shuffle the ind= ices.
 Here the Foo struct has two fields, they are tagged with const
 because no method of Foo is ever allowed to change their value
 once a Foo is built, and no one outside of Foo is allowed to
 change them. So they are quite constant.

 On the other hand if I have two or more Foos I sometimes want to
 rebind an old Foo with a new one (a simple variable assign), or
 in this program I even want to shuffle them. Shuffling them
 doesn't change the logically constant nature of their x and y
 fields.

 So in a way here I am looking for a const that makes the struct
 fields not mutable, but allows me to rebind the whole structs.

 Currently std.typecons.rebindable works only on class instances,
 interfaces and arrays (std.typecons.rebindable seems to accept
 fixed-sized arrays too, but I don't know if this meaningful &
 good). So it's not a solution.

 I think the small problem shown here is not the logical const
 needed for storing things like lazily computed hash values for
 immutable structs. Here nothing inside Foo is allowed to change
 once Foo is created (here I have not added mutable fields to Foo).

 In such situations I sometimes don't use const, or sometimes I
 use class instances, or even pointers.

 Bye,
 bearophile

Mar 15 2012
prev sibling next sibling parent "Jonathan M Davis" <jmdavisProg gmx.com> writes:
On Friday, March 16, 2012 02:43:40 bearophile wrote:
 In my code I have seen that in some situations I'd like to do
 something with structs that const doesn't allow me to do. There
 are many different cases of such usage, the following isn't my
 most common example, but it shows better what I mean:
 
 
 import std.random: randomShuffle;
 struct Foo {
 const int x, y;
 }
 void main() {
 auto foos = [Foo(1,2), Foo(3,4)];
 randomShuffle(foos);
 }
 
 
 Here the Foo struct has two fields, they are tagged with const
 because no method of Foo is ever allowed to change their value
 once a Foo is built, and no one outside of Foo is allowed to
 change them. So they are quite constant.
 
 On the other hand if I have two or more Foos I sometimes want to
 rebind an old Foo with a new one (a simple variable assign), or
 in this program I even want to shuffle them. Shuffling them
 doesn't change the logically constant nature of their x and y
 fields.
 
 So in a way here I am looking for a const that makes the struct
 fields not mutable, but allows me to rebind the whole structs.
 
 Currently std.typecons.rebindable works only on class instances,
 interfaces and arrays (std.typecons.rebindable seems to accept
 fixed-sized arrays too, but I don't know if this meaningful &
 good). So it's not a solution.
 
 I think the small problem shown here is not the logical const
 needed for storing things like lazily computed hash values for
 immutable structs. Here nothing inside Foo is allowed to change
 once Foo is created (here I have not added mutable fields to Foo).
 
 In such situations I sometimes don't use const, or sometimes I
 use class instances, or even pointers.

This situation is exactly the same as it is in C++. By making a part of the struct const, you can't assign the whole struct anymore (which is why I'd argue for _not_ making any of the fields in a struct const or immutable). The solution is usually to either make the fields private and then only provide getters but not setters (and thanks to properties, the syntax for using the struct is identical as if they were public) or to use pointer to a struct. - Jonathan M Davis
Mar 15 2012
prev sibling parent "Peter Alexander" <peter.alexander.au gmail.com> writes:
On Friday, 16 March 2012 at 01:43:41 UTC, bearophile wrote:
 So in a way here I am looking for a const that makes the struct
 fields not mutable, but allows me to rebind the whole structs.

But that would make the fields mutable: struct Foo { Foo(int _a, int _b, int _c) { a = _a; b = _b; c = _c; } int a; int b; your_const(int) c; } Foo f = Foo(1, 2, 3); f.c = 4; // illegal - good. but... f = Foo(f.a, f.b, 4); // ok? But it's the same thing.
Mar 16 2012