digitalmars.D - Error: xxx is not an lvalue
- flourish (18/18) May 02 2009 Hi,
- dennis luehring (2/18) May 02 2009 test.testMap()[0] = 1;
- flourish (3/3) May 02 2009 Thanks for your reply,
- flourish (4/27) May 02 2009 Thanks for your reply,
- Tyro[a.c.edwards] (10/27) May 02 2009 testMap() is a getter and can only return the value it is designed to.
- Denis Koroskin (27/62) May 02 2009 No, you are wrong, testMap works like a property here. I believe, origin...
- Tyro[a.c.edwards] (3/29) May 02 2009 Thanks for the clarification.
- Unknown W. Brackets (18/46) May 03 2009 This code works fine (D 2.x only):
- Tyro[a.c.edwards] (13/59) May 03 2009 Is this an intended or even desirable "feature" of the language or just
- Unknown W. Brackets (15/84) May 03 2009 Well, if you really want a "protected" associative array, or array for
- Tyro[a.c.edwards] (17/101) May 03 2009 I was following until now... If I can modify said private member at a
- Unknown W. Brackets (39/155) May 03 2009 You can do that something similar to that, sure.
- Steven Schveighoffer (5/19) May 04 2009 The original code should work, this is a problem. An AA is not a value ...
- Unknown W. Brackets (14/39) May 04 2009 I've always though of arrays and associative arrays as structs (which
- Steven Schveighoffer (24/37) May 04 2009 The underlying struct of an AA is:
- Unknown W. Brackets (6/56) May 04 2009 If that's the structure, then yes, I agree.
- Steven Schveighoffer (25/29) May 04 2009 You had me doubting myself ;) So I looked it up
Hi, why does the following code not compile -- or how to declare a (usable) property of an associative array field? ////////////////////// class Test { private int[int] _testMap; public int[int] testMap() {return _testMap;} } void main() { Test test = new Test(); test.testMap[0] = 1; } ///////////////// *** Error: test.testMap() is not an lvalue Regards, flourish
May 02 2009
On 02.05.2009 20:44, flourish wrote:Hi, why does the following code not compile -- or how to declare a (usable) property of an associative array field? ////////////////////// class Test { private int[int] _testMap; public int[int] testMap() {return _testMap;} } void main() { Test test = new Test(); test.testMap[0] = 1; } ///////////////// *** Error: test.testMap() is not an lvaluetest.testMap()[0] = 1;
May 02 2009
Thanks for your reply, but I get the same error when using: test.testMap()[0] = 1;
May 02 2009
Thanks for your reply, but I get the same error when using: test.testMap()[0] = 1; == Quote from dennis luehring (dl.soluz gmx.net)'s articleOn 02.05.2009 20:44, flourish wrote:Hi, why does the following code not compile -- or how to declare a (usable) property of an associative array field? ////////////////////// class Test { private int[int] _testMap; public int[int] testMap() {return _testMap;} } void main() { Test test = new Test(); test.testMap[0] = 1; } ///////////////// *** Error: test.testMap() is not an lvaluetest.testMap()[0] = 1;
May 02 2009
On 5/3/2009 3:44 AM, flourish wrote:Hi, why does the following code not compile -- or how to declare a (usable) property of an associative array field? ////////////////////// class Test { private int[int] _testMap; public int[int] testMap() {return _testMap;}public void opIndexAssign(int val, int ndx){ _testMap[ndx] = val; }}testMap() is a getter and can only return the value it is designed to. You must implement a setter to accomplish what you are trying to do. Unfortunately I'm not sure how to do it with AAs so I'll leave the details to someone that's a little smarter than I. I think that maybe implementing opIndexAssign might do the trick though. See modifications to Test and main().void main() { Test test = new Test();//test.testMap[0] = 1; // Error: getters cannot be assigned to test[0] = 1;} ///////////////// *** Error: test.testMap() is not an lvalue Regards, flourish
May 02 2009
On Sun, 03 May 2009 01:02:41 +0400, Tyro[a.c.edwards] <nospam home.com> wrote:On 5/3/2009 3:44 AM, flourish wrote:No, you are wrong, testMap works like a property here. I believe, original code _should_ work. For example, it works if you replace int[int] with int[]. All the trouble is because of an awful properties implementation in D, and temporaries not being able to be passed by reference: struct Foo { private int[] _arr; int[] arr() { return _arr; } } void doSomething(int[] a) { } void doSomethingElse(ref int[] a) { } void doSomethingElseConst(ref const(int)[] a) { } void main() { Foo foo; foo.arr[0] = 1; // works //foo.arr.length = 1; // doesn't foo.arr().doSomething(); // works //foo.arr.doSomething(); // doesn't //foo.arr().doSomethingElse(); // doesn't //foo.arr().doSomethingElseConst(); // doesn't }Hi, why does the following code not compile -- or how to declare a (usable) property of an associative array field? ////////////////////// class Test { private int[int] _testMap; public int[int] testMap() {return _testMap;} }testMap() is a getter and can only return the value it is designed to. You must implement a setter to accomplish what you are trying to di. Unfortunately I'm not sure how you do that with AAs so I'll leave that to someone that's a little smarter than I. I think that maybe implementing opIndexAssign might work for you though: public void opIndexAssign(int val, int ndx){ _testMap[ndx] = val; } Then you can simply "test[0] = 1;" to get the desired effect.void main() { Test test = new Test(); test.testMap[0] = 1; } ///////////////// *** Error: test.testMap() is not an lvalue Regards, flourish
May 02 2009
On 5/3/2009 6:36 AM, Denis Koroskin wrote:On Sun, 03 May 2009 01:02:41 +0400, Tyro[a.c.edwards] <nospam home.com> wrote:[...]On 5/3/2009 3:44 AM, flourish wrote:Hi, why does the following code not compile -- or how to declare a (usable) property of an associative array field? ////////////////////// class Test { private int[int] _testMap; public int[int] testMap() {return _testMap;} }testMap() is a getter and can only return the value it is designed to. You must implement a setter to accomplish what you are trying to di. Unfortunately I'm not sure how you do that with AAs so I'll leave that to someone that's a little smarter than I.No, you are wrong, testMap works like a property here. I believe, original code _should_ work. For example, it works if you replace int[int] with int[]. All the trouble is because of an awful properties implementation in D, and temporaries not being able to be passed by reference:Thanks for the clarification.
May 02 2009
This code works fine (D 2.x only): class Test { private int[int] _testMap; public ref int[int] testMap() {return _testMap;} } void main() { Test test = new Test(); test.testMap[0] = 1; } Note the "ref". Otherwise, a value is returned which is not modifiable. This will also fix test.array.length. Nothing wrong here, no creepy bad temporary property problems. I suppose you could also try returning a pointer to an associative array (e.g. with &) in D 1.x. -[Unknown] flourish wrote:Hi, why does the following code not compile -- or how to declare a (usable) property of an associative array field? ////////////////////// class Test { private int[int] _testMap; public int[int] testMap() {return _testMap;} } void main() { Test test = new Test(); test.testMap[0] = 1; } ///////////////// *** Error: test.testMap() is not an lvalue Regards, flourish
May 03 2009
On 5/3/2009 6:25 PM, Unknown W. Brackets wrote:This code works fine (D 2.x only): class Test { private int[int] _testMap; public ref int[int] testMap() {return _testMap;} } void main() { Test test = new Test(); test.testMap[0] = 1; } Note the "ref". Otherwise, a value is returned which is not modifiable. This will also fix test.array.length. Nothing wrong here, no creepy bad temporary property problems.Is this an intended or even desirable "feature" of the language or just something that happens to work in D 2.x? I ask because to the untrained eye, it is unclear exactly what is happening. There is nothing to inform me that _testMap can be modified from outside the class. Even with "ref" there it doesn't make it any clearer. Matter of fact, I just had a problem in Phobos 2 where a function was defined like that and I had to comment out the "ref" for it to work. Kept telling me that some array was not an lvalue. The minute I commented out the "ref", everything worked like a charm. Also it makes more sense to me to have separate functions as getters and setters. Maybe that's only because I lacking proper training in the art of computer programming though.I suppose you could also try returning a pointer to an associative array (e.g. with &) in D 1.x. -[Unknown] flourish wrote:Hi, why does the following code not compile -- or how to declare a (usable) property of an associative array field? ////////////////////// class Test { private int[int] _testMap; public int[int] testMap() {return _testMap;} } void main() { Test test = new Test(); test.testMap[0] = 1; } ///////////////// *** Error: test.testMap() is not an lvalue Regards, flourish
May 03 2009
Well, if you really want a "protected" associative array, or array for that matter, you probably should define a wrapper class that inlines the access you're willing to allow. From a basic perspective, _testMap is a structure of data. Although it is private, there's no reason it can't be modified through an accessor. Without a setter, the only thing that should fail is test.testMap = something. Requiring a setter for any minor change makes no sense. Compare it to this: if you have a class that has a member object (e.g. a User with a Socket member variable), should it be necessary to have a setter to change the Socket? Can't the Socket handle its own private/public-ness? Arrays and associative arrays are the same, except that the members you use are public. -[Unknown] Tyro[a.c.edwards] wrote:On 5/3/2009 6:25 PM, Unknown W. Brackets wrote:This code works fine (D 2.x only): class Test { private int[int] _testMap; public ref int[int] testMap() {return _testMap;} } void main() { Test test = new Test(); test.testMap[0] = 1; } Note the "ref". Otherwise, a value is returned which is not modifiable. This will also fix test.array.length. Nothing wrong here, no creepy bad temporary property problems.Is this an intended or even desirable "feature" of the language or just something that happens to work in D 2.x? I ask because to the untrained eye, it is unclear exactly what is happening. There is nothing to inform me that _testMap can be modified from outside the class. Even with "ref" there it doesn't make it any clearer. Matter of fact, I just had a problem in Phobos 2 where a function was defined like that and I had to comment out the "ref" for it to work. Kept telling me that some array was not an lvalue. The minute I commented out the "ref", everything worked like a charm. Also it makes more sense to me to have separate functions as getters and setters. Maybe that's only because I lacking proper training in the art of computer programming though.I suppose you could also try returning a pointer to an associative array (e.g. with &) in D 1.x. -[Unknown] flourish wrote:Hi, why does the following code not compile -- or how to declare a (usable) property of an associative array field? ////////////////////// class Test { private int[int] _testMap; public int[int] testMap() {return _testMap;} } void main() { Test test = new Test(); test.testMap[0] = 1; } ///////////////// *** Error: test.testMap() is not an lvalue Regards, flourish
May 03 2009
On 5/3/2009 8:17 PM, Unknown W. Brackets wrote:Well, if you really want a "protected" associative array, or array for that matter, you probably should define a wrapper class that inlines the access you're willing to allow. From a basic perspective, _testMap is a structure of data. Although it is private, there's no reason it can't be modified through an accessor. Without a setter, the only thing that should fail is test.testMap = something. Requiring a setter for any minor change makes no sense.I was following until now... If I can modify said private member at a whim, why on earth would I prevent this case? Is this because I would be assigning it a completely new value vice simply modifying its content? If that is the case, am I correct in saying that this characteristic is applicable only to arrays?Compare it to this: if you have a class that has a member object (e.g. a User with a Socket member variable), should it be necessary to have a setter to change the Socket? Can't the Socket handle its own private/public-ness? Arrays and associative arrays are the same, except that the members you use are public. -[Unknown]Got you... I think I understand. That being the case though, wouldn't it be just as useful to build the same "accessor" capability into opAssign such that you can: class Foo { private sometype _data; public ref typeof(_data) opAssign() { return _data; } } Foo b = new foo; b[0] = 1; Why is it necessary to have a separate/different "accessor" function?Tyro[a.c.edwards] wrote:On 5/3/2009 6:25 PM, Unknown W. Brackets wrote:This code works fine (D 2.x only): class Test { private int[int] _testMap; public ref int[int] testMap() {return _testMap;} } void main() { Test test = new Test(); test.testMap[0] = 1; } Note the "ref". Otherwise, a value is returned which is not modifiable. This will also fix test.array.length. Nothing wrong here, no creepy bad temporary property problems.Is this an intended or even desirable "feature" of the language or just something that happens to work in D 2.x? I ask because to the untrained eye, it is unclear exactly what is happening. There is nothing to inform me that _testMap can be modified from outside the class. Even with "ref" there it doesn't make it any clearer. Matter of fact, I just had a problem in Phobos 2 where a function was defined like that and I had to comment out the "ref" for it to work. Kept telling me that some array was not an lvalue. The minute I commented out the "ref", everything worked like a charm. Also it makes more sense to me to have separate functions as getters and setters. Maybe that's only because I lacking proper training in the art of computer programming though.I suppose you could also try returning a pointer to an associative array (e.g. with &) in D 1.x. -[Unknown] flourish wrote:Hi, why does the following code not compile -- or how to declare a (usable) property of an associative array field? ////////////////////// class Test { private int[int] _testMap; public int[int] testMap() {return _testMap;} } void main() { Test test = new Test(); test.testMap[0] = 1; } ///////////////// *** Error: test.testMap() is not an lvalue Regards, flourish
May 03 2009
You can do that something similar to that, sure. But, you'd be implementing a class and doing an opIndexAssign. That's totally different from just returning the associative array outright. What you'd do to make a non-modifyable array is this: class Foo(T) { private T[] data; public ref T opIndex(int i) { return this.data[i]; } /* public ref T opIndexAssign(int i, T val) { // Do some sort of validation. this.data[i] = val; return this.data[i]; } */ } But, maybe you want the associative array to be modifiable? For example, I have an XPath library, and in it I just have a namespaces member. I place no logic on this, so the interface to add namespaces is as simple as modifying the associative array (e.g. .namespaces["xhtml"] = "http://www.w3.org/1999/xhtml".) You have the control to do either one. But, a member being private just means the user of the class cannot access the member *though that method or means*. It does not affect the data, it doesn't make it special or non-modifiable, and it shouldn't. As to your other question - there are good reasons for that. For example, suppose I had a database class. If I have an instance of the database connection as a member of the result class, I don't mind if you modify the connection through that member variable. However, if you were to reassign the member (e.g. = new DBConnection()), that wouldn't make sense and could cause me serious problems. The connection class can manage what parts of it you can modify or not, so as long as I force you to use the one I already have, I'm safe. -[Unknown] Tyro[a.c.edwards] wrote:On 5/3/2009 8:17 PM, Unknown W. Brackets wrote:Well, if you really want a "protected" associative array, or array for that matter, you probably should define a wrapper class that inlines the access you're willing to allow. From a basic perspective, _testMap is a structure of data. Although it is private, there's no reason it can't be modified through an accessor. Without a setter, the only thing that should fail is test.testMap = something. Requiring a setter for any minor change makes no sense.I was following until now... If I can modify said private member at a whim, why on earth would I prevent this case? Is this because I would be assigning it a completely new value vice simply modifying its content? If that is the case, am I correct in saying that this characteristic is applicable only to arrays?Compare it to this: if you have a class that has a member object (e.g. a User with a Socket member variable), should it be necessary to have a setter to change the Socket? Can't the Socket handle its own private/public-ness? Arrays and associative arrays are the same, except that the members you use are public. -[Unknown]Got you... I think I understand. That being the case though, wouldn't it be just as useful to build the same "accessor" capability into opAssign such that you can: class Foo { private sometype _data; public ref typeof(_data) opAssign() { return _data; } } Foo b = new foo; b[0] = 1; Why is it necessary to have a separate/different "accessor" function?Tyro[a.c.edwards] wrote:On 5/3/2009 6:25 PM, Unknown W. Brackets wrote:This code works fine (D 2.x only): class Test { private int[int] _testMap; public ref int[int] testMap() {return _testMap;} } void main() { Test test = new Test(); test.testMap[0] = 1; } Note the "ref". Otherwise, a value is returned which is not modifiable. This will also fix test.array.length. Nothing wrong here, no creepy bad temporary property problems.Is this an intended or even desirable "feature" of the language or just something that happens to work in D 2.x? I ask because to the untrained eye, it is unclear exactly what is happening. There is nothing to inform me that _testMap can be modified from outside the class. Even with "ref" there it doesn't make it any clearer. Matter of fact, I just had a problem in Phobos 2 where a function was defined like that and I had to comment out the "ref" for it to work. Kept telling me that some array was not an lvalue. The minute I commented out the "ref", everything worked like a charm. Also it makes more sense to me to have separate functions as getters and setters. Maybe that's only because I lacking proper training in the art of computer programming though.I suppose you could also try returning a pointer to an associative array (e.g. with &) in D 1.x. -[Unknown] flourish wrote:Hi, why does the following code not compile -- or how to declare a (usable) property of an associative array field? ////////////////////// class Test { private int[int] _testMap; public int[int] testMap() {return _testMap;} } void main() { Test test = new Test(); test.testMap[0] = 1; } ///////////////// *** Error: test.testMap() is not an lvalue Regards, flourish
May 03 2009
On Sun, 03 May 2009 05:25:09 -0400, Unknown W. Brackets <unknown simplemachines.org> wrote:This code works fine (D 2.x only): class Test { private int[int] _testMap; public ref int[int] testMap() {return _testMap;} } void main() { Test test = new Test(); test.testMap[0] = 1; } Note the "ref". Otherwise, a value is returned which is not modifiable. This will also fix test.array.length. Nothing wrong here, no creepy bad temporary property problems.The original code should work, this is a problem. An AA is not a value type. -Steve
May 04 2009
I've always though of arrays and associative arrays as structs (which really is what they are.) Thinking that way, this behavior makes exact sense - down to .length being unchangeable and associative arrays being unchangeable. I mean, you wouldn't want to make it work the way you suggest by making arrays and associative arrays simply pointers to their current structs (just like a class would be.) You could make such a class easily yourself, anyway. If you are right, I guess the right solution would be to make the ref implicit when returning (or, I suppose, passing?) such arrays and associative arrays. But that seems wrong to me too, and wouldn't come free (speaking of efficiency) either. -[Unknown] Steven Schveighoffer wrote:On Sun, 03 May 2009 05:25:09 -0400, Unknown W. Brackets <unknown simplemachines.org> wrote:This code works fine (D 2.x only): class Test { private int[int] _testMap; public ref int[int] testMap() {return _testMap;} } void main() { Test test = new Test(); test.testMap[0] = 1; } Note the "ref". Otherwise, a value is returned which is not modifiable. This will also fix test.array.length. Nothing wrong here, no creepy bad temporary property problems.The original code should work, this is a problem. An AA is not a value type. -Steve
May 04 2009
On Mon, 04 May 2009 14:53:41 -0400, Unknown W. Brackets <unknown simplemachines.org> wrote:I've always though of arrays and associative arrays as structs (which really is what they are.) Thinking that way, this behavior makes exact sense - down to .length being unchangeable and associative arrays being unchangeable. I mean, you wouldn't want to make it work the way you suggest by making arrays and associative arrays simply pointers to their current structs (just like a class would be.) You could make such a class easily yourself, anyway. If you are right, I guess the right solution would be to make the ref implicit when returning (or, I suppose, passing?) such arrays and associative arrays. But that seems wrong to me too, and wouldn't come free (speaking of efficiency) either. -[Unknown]The underlying struct of an AA is: struct AA { AA_Implementation *impl; } or something like that ;) Look at the D runtime source. But in any case, if you return an array slice, would you not want to be able to update an element of the slice? I think there is a difference between a value struct (where all internals are non-reference types), and a reference struct (where at least one element is a reference type). A reference struct should be able to pass those references to other functions without having to be ref'd. It forces non-transparent type wrapping if that isn't the case. I should be able to replace a reference or pointer type with a wrapper struct where I can modify the interface, and it should be transparent that I have done so (except for the interface changes of course). I think this is one of the goals D2 is working towards. It makes sense that a value struct or the value types inside a reference struct (i.e. the length of an array) should not be changeable as rvalues, since you aren't going to use them later. Both arrays (as the current implementation) and AA's are reference structs. -Steve
May 04 2009
If that's the structure, then yes, I agree. Long time ago (before D 1.x?) I looked at the associative array implementation and it was a struct with a few members. I didn't realize it had changed. Or maybe I'm just remembering wrong. -[Unknown] Steven Schveighoffer wrote:On Mon, 04 May 2009 14:53:41 -0400, Unknown W. Brackets <unknown simplemachines.org> wrote:I've always though of arrays and associative arrays as structs (which really is what they are.) Thinking that way, this behavior makes exact sense - down to .length being unchangeable and associative arrays being unchangeable. I mean, you wouldn't want to make it work the way you suggest by making arrays and associative arrays simply pointers to their current structs (just like a class would be.) You could make such a class easily yourself, anyway. If you are right, I guess the right solution would be to make the ref implicit when returning (or, I suppose, passing?) such arrays and associative arrays. But that seems wrong to me too, and wouldn't come free (speaking of efficiency) either. -[Unknown]The underlying struct of an AA is: struct AA { AA_Implementation *impl; } or something like that ;) Look at the D runtime source. But in any case, if you return an array slice, would you not want to be able to update an element of the slice? I think there is a difference between a value struct (where all internals are non-reference types), and a reference struct (where at least one element is a reference type). A reference struct should be able to pass those references to other functions without having to be ref'd. It forces non-transparent type wrapping if that isn't the case. I should be able to replace a reference or pointer type with a wrapper struct where I can modify the interface, and it should be transparent that I have done so (except for the interface changes of course). I think this is one of the goals D2 is working towards. It makes sense that a value struct or the value types inside a reference struct (i.e. the length of an array) should not be changeable as rvalues, since you aren't going to use them later. Both arrays (as the current implementation) and AA's are reference structs. -Steve
May 04 2009
On Mon, 04 May 2009 16:28:06 -0400, Unknown W. Brackets <unknown simplemachines.org> wrote:If that's the structure, then yes, I agree. Long time ago (before D 1.x?) I looked at the associative array implementation and it was a struct with a few members. I didn't realize it had changed. Or maybe I'm just remembering wrong.You had me doubting myself ;) So I looked it up From the aaA.d file (of dmd 1.043): struct aaA { aaA *left; aaA *right; hash_t hash; /* key */ /* value */ } struct BB { aaA*[] b; size_t nodes; // total number of aaA nodes } /* This is the type actually seen by the programmer, although * it is completely opaque. */ struct AA { BB* a; } -Steve
May 04 2009