digitalmars.D.learn - I need some help here.
- Damian (37/37) Aug 30 2006 Suppose I have a class like this:
- Chris Nicholson-Sauls (20/65) Aug 30 2006 Two ways. First way, if it makes sense you might overload the index ope...
- Reiner Pope (26/95) Aug 31 2006 This is really the immutability problem again. Basically, you want to
- Damian (11/69) Aug 31 2006 Well, I thought I was missing a "const" somewhere, but it's a little mor...
- Damian (18/37) Aug 31 2006 I would have to use
- Chris Nicholson-Sauls (6/32) Aug 31 2006 Actually yes it could, as all members of the same module have implicit "...
- Reiner Pope (28/33) Aug 31 2006 No, that's not quite what I meant. Your class (cl) would look like this:
Suppose I have a class like this: class cl{ private: char[][] _data; int _maxDataLength; public: char[][] data(){ _return data; } void data(char[][] d){ _maxDataLength = calculateMaxDataLength(d); _data = d; } int maxDataLength(){ return _maxDataLength; } private: int calculateMaxDataLength(char[][] data){ // this takes time. } } And in a function I do something like this: // dClass is a global cl object. char[][] d = dClass.data; d[3] = "naranja"; int dlength = dClass.maxDataLength; then dlength won't be valid, since _data has changed but _maxDataLength wasn't updated. How can I avoid this? I know that int maxDataLength(){ return calculateMaxDataLength(_data); } will solve the problem, but I don't want to call calculateMaxDataLength if the intention is to to see the data without modifying it. Thanks.
Aug 30 2006
Damian wrote:Suppose I have a class like this: class cl{ private: char[][] _data; int _maxDataLength; public: char[][] data(){ _return data; } void data(char[][] d){ _maxDataLength = calculateMaxDataLength(d); _data = d; } int maxDataLength(){ return _maxDataLength; } private: int calculateMaxDataLength(char[][] data){ // this takes time. } } And in a function I do something like this: // dClass is a global cl object. char[][] d = dClass.data; d[3] = "naranja"; int dlength = dClass.maxDataLength; then dlength won't be valid, since _data has changed but _maxDataLength wasn't updated. How can I avoid this? I know that int maxDataLength(){ return calculateMaxDataLength(_data); } will solve the problem, but I don't want to call calculateMaxDataLength if the intention is to to see the data without modifying it. Thanks.Two ways. First way, if it makes sense you might overload the index operators for your class. If that doesn't make logical sense, then there is the .dup property which will create a safe copy: I don't remember ever using .dup with multi-dimensional arrays, though, so it may have to be something more like: I would say experiment with the first one first. I imagine it should work fine, and is certainly less work than the second. -- Chris Nicholson-Sauls
Aug 30 2006
Chris Nicholson-Sauls wrote:Damian wrote:This is really the immutability problem again. Basically, you want to either: - not allow modification of _data; or - be aware when _data is changed. Chris's suggestion (dup'ing it) achieves the first, and providing the index operator achieves the second by intercepting indexing calls. Another suggestion, if you don't want to overload indexing for your class is to create an array wrapper which notifies your class on changes: class MyArray(T) { private T[] _data; T opIndexAssign(uint index, T value) { notifyThatDataHasChanged(); return _data[index] = value; } T opIndex(uint index) { return _data[index]; } ... } This means that you can use your class's opIndex for something else. Alternatively, you could use this interface to return an immutable version of _data, just by not supporting opIndexAssign. Cheers, ReinerSuppose I have a class like this: class cl{ private: char[][] _data; int _maxDataLength; public: char[][] data(){ _return data; } void data(char[][] d){ _maxDataLength = calculateMaxDataLength(d); _data = d; } int maxDataLength(){ return _maxDataLength; } private: int calculateMaxDataLength(char[][] data){ // this takes time. } } And in a function I do something like this: // dClass is a global cl object. char[][] d = dClass.data; d[3] = "naranja"; int dlength = dClass.maxDataLength; then dlength won't be valid, since _data has changed but _maxDataLength wasn't updated. How can I avoid this? I know that int maxDataLength(){ return calculateMaxDataLength(_data); } will solve the problem, but I don't want to call calculateMaxDataLength if the intention is to to see the data without modifying it. Thanks.Two ways. First way, if it makes sense you might overload the index operators for your class. If that doesn't make logical sense, then there is the .dup property which will create a safe copy: I don't remember ever using .dup with multi-dimensional arrays, though, so it may have to be something more like: I would say experiment with the first one first. I imagine it should work fine, and is certainly less work than the second. -- Chris Nicholson-Sauls
Aug 31 2006
Well, I thought I was missing a "const" somewhere, but it's a little more complicated. :S 1st choice: Make a copy of 2-dim array seems to be a waste of time to this specific problem. 2nd choice: My class is not a "data" class, it just works with some data, so overload index ops in my class isn't clear, I think. 3rd choice:I don't want to make a class wrapper since all I need is an array, but well, I think I can do it once and use it once and again, so I'll take this choice! Anyway, I think I miss "const". Why is not part of D? Thanks you both for your help!Two ways. First way, if it makes sense you might overload the index operators for your class. If that doesn't make logical sense, then there is the .dup property which will create a safe copy: I don't remember ever using .dup with multi-dimensional arrays, though, so it may have to be something more like: I would say experiment with the first one first. I imagine it should work fine, and is certainly less work than the second. -- Chris Nicholson-SaulsThis is really the immutability problem again. Basically, you want to either: - not allow modification of _data; or - be aware when _data is changed. Chris's suggestion (dup'ing it) achieves the first, and providing the index operator achieves the second by intercepting indexing calls. Another suggestion, if you don't want to overload indexing for your class is to create an array wrapper which notifies your class on changes: class MyArray(T) { private T[] _data; T opIndexAssign(uint index, T value) { notifyThatDataHasChanged(); return _data[index] = value; } T opIndex(uint index) { return _data[index]; } ... } This means that you can use your class's opIndex for something else. Alternatively, you could use this interface to return an immutable version of _data, just by not supporting opIndexAssign. Cheers, Reiner
Aug 31 2006
class MyArray(T) { private T[] _data; T opIndexAssign(uint index, T value) { notifyThatDataHasChanged(); return _data[index] = value; } T opIndex(uint index) { return _data[index]; } ... } This means that you can use your class's opIndex for something else. Alternatively, you could use this interface to return an immutable version of _data, just by not supporting opIndexAssign.I would have to use MyArray!(MyArray!(char)) _data; for _data to be really immutable. Anyway, I can't do this that way, since my class "cl" couldnt modify _data either. I think I will do something like this: private: char[][] _data; int _maxDataLength; public: /** _DO NOT_ modify data this way, use "void data(char[][] d)" */ char[][] data(){ _return data; } void data(char[][] d){ _maxDataLength = calculateMaxDataLength(d); _data = d; }
Aug 31 2006
Damian wrote:Actually yes it could, as all members of the same module have implicit "friend" relationships. So, since 'c1' and the wrapper class (which should probably be a nested class anyhow) would be in the same module, 'c1' would have access to the wrapper's private 'data' field. -- Chris Nicholson-Saulsclass MyArray(T) { private T[] _data; T opIndexAssign(uint index, T value) { notifyThatDataHasChanged(); return _data[index] = value; } T opIndex(uint index) { return _data[index]; } ... } This means that you can use your class's opIndex for something else. Alternatively, you could use this interface to return an immutable version of _data, just by not supporting opIndexAssign.I would have to use MyArray!(MyArray!(char)) _data; for _data to be really immutable. Anyway, I can't do this that way, since my class "cl" couldnt modify _data either.
Aug 31 2006
Damian wrote:I would have to use MyArray!(MyArray!(char)) _data; for _data to be really immutable. Anyway, I can't do this that way, since my class "cl" couldnt modify _data either.No, that's not quite what I meant. Your class (cl) would look like this: class cl{ private: char[][] _data; int _maxDataLength; public: MyArray!(MyArray!(char)) data() { // Construct a MyArray which represents a readonly view of the data } int maxDataLength(){ return _maxDataLength; } private: int calculateMaxDataLength(char[][] data){ // this takes time. } } The constructor would be annoying to write, though, because you would need to recursively generate one for each level of the array. However, a bit of template magic could be your solution here, I think. Yes, from your other post, const is really what you need, and many people find it lacking. However, it is way too complex to rush, and there has not yet been a perfect solution proposed. There probably never will be, so D may remain without const. Cheers, Reiner
Aug 31 2006