digitalmars.D.learn - Getting consistent behavour for class properties
- mikey (59/59) Oct 02 2016 Hi,
- mikey (4/6) Oct 02 2016 Sorry that should have of course read:
- Lodovico Giaretta (17/18) Oct 02 2016 Yeah, a property is quite different from a variable. In fact, a
- mikey (16/25) Oct 02 2016 There is already a degree of transparency with how properties
- Lodovico Giaretta (8/12) Oct 02 2016 Actually, this is not specific to properties, as it also works on
- Kagamin (1/1) Oct 03 2016 I suppose that's https://issues.dlang.org/show_bug.cgi?id=8006
- mikey (3/4) Oct 09 2016 Yes, exactly. Although, I don't see why they wrap it in a struct
Hi, I'm experimenting with the behaviour of properties in D, as I am writing some classes that are being used in a mixture of const and non-const functions. I've found a couple of things that I'd just like to check. First perhaps I should say what I would expect from working with properties in a mixed const / non-const environment. * I expect getting a property to work for both const and non-const. * I expect setting a property to only work for non-const. I found that to get this behaviour I needed to declare any getter return type as well as the property function as "inout". This seemed to work for getter / setter function pairs as well as the " property auto ref" idiom. I also noticed something that was unexpected to me as a beginner, that the getter / setter pairs are not valid with the "+=" operator but the "auto ref" is. I guess this is down to the way D interprets the syntax during compilation and the differences between how the 2 different implementations access the data. But it is none the less surprising that the flowing are not syntactically equivalent. t.val = t.val + 1; t.val += t.val; Anyway here is my test code: module test; class Test { private: int _val; public: property inout(int) val() inout { return _val; } property void val(int val) { _val = val; } property auto ref inout(int) val2() inout { return _val; } } void test(Test t) { import std.stdio : writeln; writeln("--- test ----"); writeln("val: ", t.val); writeln("val2: ", t.val2); } void test2(in Test t) { import std.stdio : writeln; writeln("--- test 2 ----"); writeln("val: ", t.val); writeln("val2: ", t.val2); } void main() { auto t = new Test; //t.val += 100; // BAD - not an lvalue t.val = t.val + 100; test(t); t.val2 += 100; // OK test2(t); }
Oct 02 2016
On Sunday, 2 October 2016 at 14:26:46 UTC, mikey wrote:t.val = t.val + 1; t.val += t.val;Sorry that should have of course read: t.val = t.val + 1; t.val += 1;
Oct 02 2016
On Sunday, 2 October 2016 at 14:26:46 UTC, mikey wrote:[...]Yeah, a property is quite different from a variable. In fact, a property may refer to a computed value, which may not have an address and as such cannot be modified: property auto currentTimeMillis() { return currentTimeNanos/1000000; } So it is correct that `+=` doesn't work with properties, and neither does the "addressof" operator `&` (it returns the delegate). Having a getter property return by ref circumvents this issue, but has the drawback of bypassing any check that a setter property would do. If you want to use properties as getters/setters and also want compound assignments to work, you can easily achieve that with a wrapper template as this[1] one. [1] http://pastebin.com/38n0fEtF
Oct 02 2016
On Sunday, 2 October 2016 at 14:44:13 UTC, Lodovico Giaretta wrote:Yeah, a property is quite different from a variable. In fact, a property may refer to a computed value, which may not have an address and as such cannot be modified: [...] So it is correct that `+=` doesn't work with properties, and neither does the "addressof" operator `&` (it returns the delegate). Having a getter property return by ref circumvents this issue, but has the drawback of bypassing any check that a setter property would do.There is already a degree of transparency with how properties being handled for example in allowing properties to be an lvalue if they have a setter. t.val = 42; I can understand that on an implementation level it might be simpler to interpret the 2 statements differently but it would seem much more intuitive to me if the syntactic sugar for properties were extended out to allow statements such as: t.val += 1; Where there is a getter and setter available. To my mind at least the ideal would be for properties to act as close as possible to member variables. It is however good to see that it's possible to wrap functions to provide some of this behaviour.
Oct 02 2016
On Sunday, 2 October 2016 at 17:10:58 UTC, mikey wrote:There is already a degree of transparency with how properties being handled for example in allowing properties to be an lvalue if they have a setter. t.val = 42;Actually, this is not specific to properties, as it also works on "standard" methods, if they have a single parameter: import std.stdio; void main() { writeln = 42; }
Oct 02 2016
I suppose that's https://issues.dlang.org/show_bug.cgi?id=8006
Oct 03 2016
On Monday, 3 October 2016 at 14:05:24 UTC, Kagamin wrote:I suppose that's https://issues.dlang.org/show_bug.cgi?id=8006Yes, exactly. Although, I don't see why they wrap it in a struct in the example as this seems to me to just obfuscate the issue.
Oct 09 2016