www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Properties don't work as expected

reply zodd <zodd maill.com> writes:
Property functions are used wrong by a compiler when it needs to 
get and set a value at the same time:

import std.stdio;

struct A {
      property int value() const {
         return value_;
     }

      property ref int value(int v) {
		value_ = v;
		return value_;
     }

private:
	int value_;
}

int main(string[] args) {
	A a;
	a.value += 20; // <<<<< Error: a.value() is not an lvalue
	return 0;
}


It's a very inconvenient. Why don't just call a getter and then a 
setter functions in such cases?
I found the D language specification and it doesn't bother to 
explain how properties should behave in such cases. Is there a 
full language specification somewhere?
Also, I've googled a little and found a similar topic from 2012 
(http://forum.dlang.org/thread/srhwzxgpiqucknchenot forum.dlang.org). So, since
2012 nobody cared about it? What a shame!
Even a D Wiki page with properties discussion 
(https://wiki.dlang.org/Property_Discussion_Wrap-up) gives an 
example of property usage, which can't be compiled by the latest 
version of dmd:

a.weeks++;
a.weeks -=2;

Is there a chance, that this weird behavior will be fixed in the 
near future? What can I do to help fix it?
Jul 05 2016
next sibling parent reply Satoshi <satoshi rikarin.org> writes:
On Tuesday, 5 July 2016 at 10:52:10 UTC, zodd wrote:
 Property functions are used wrong by a compiler when it needs 
 to get and set a value at the same time:

 [...]
Try property ref int value() { return value_; }
Jul 05 2016
parent zodd <zodd maill.com> writes:
On Tuesday, 5 July 2016 at 11:02:11 UTC, Satoshi wrote:
 On Tuesday, 5 July 2016 at 10:52:10 UTC, zodd wrote:
 Property functions are used wrong by a compiler when it needs 
 to get and set a value at the same time:

 [...]
Try property ref int value() { return value_; }
What if I need a setter function? I would never bother with properties and just used the field itself otherwise.
Jul 05 2016
prev sibling next sibling parent reply ketmar <ketmar ketmar.no-ip.org> writes:
On Tuesday, 5 July 2016 at 10:52:10 UTC, zodd wrote:
 It's a very inconvenient. Why don't just call a getter and then 
 a setter functions in such cases?
'cause property specs aren't even finalized yet.
 Is there a chance, that this weird behavior will be fixed in 
 the near future? What can I do to help fix it?
almost as much as you can expect snowfall in hell.
Jul 05 2016
parent reply zodd <zodd maill.com> writes:
On Tuesday, 5 July 2016 at 12:45:33 UTC, ketmar wrote:
 Is there a chance, that this weird behavior will be fixed in 
 the near future? What can I do to help fix it?
almost as much as you can expect snowfall in hell.
Why do you have so pessimistic opinion? Is D a perspective language to learn or it's stagnating and never be production ready?
Jul 05 2016
next sibling parent Leandro Motta Barros via Digitalmars-d-learn writes:
D is being used productively by some companies, so I guess we can call it
production-ready. This doesn't meant there are not rough corners. The
language is being actively developed, and I see that some work is being
done on those rough corners. However, keep in mind that:

1) Maybe what you perceive as a strong deficiency isn't seen as a top
priority for the D developers. This issue with properties, for instance, is
annoying (I agree with you!), but most of the time (if not ever) it can be
easily circumvented (as Satoshi has shown).

2) Sometimes, changing language features have subtle side effects, and the
devs must take everything into account. A fix that looks obvious for us
mere mortals can actually open a can of worms and introduce many new issues.

Hope this answers your quesiton,

LMB


On Tue, Jul 5, 2016 at 10:14 AM, zodd via Digitalmars-d-learn <
digitalmars-d-learn puremagic.com> wrote:

 On Tuesday, 5 July 2016 at 12:45:33 UTC, ketmar wrote:

 Is there a chance, that this weird behavior will be fixed in the near
 future? What can I do to help fix it?
almost as much as you can expect snowfall in hell.
Why do you have so pessimistic opinion? Is D a perspective language to learn or it's stagnating and never be production ready?
Jul 05 2016
prev sibling parent reply ketmar <ketmar ketmar.no-ip.org> writes:
On Tuesday, 5 July 2016 at 13:14:29 UTC, zodd wrote:
 Why do you have so pessimistic opinion?
it is realistic.
 Is D a perspective language to learn or it's stagnating and 
 never be production ready?
what do you want here: "non-stagnating" or "production ready"? D is "production ready", and that means that D should be STABLE. we can't introduce features just 'cause they are cool. we can't even change the features without long and hard discussion. if we'll finalize property specs, we'll stick with it forever. and devs have many other things to do too, most of it for free and in their spare time. that's why finalizing properties is postponed, for undefined time. you *can* workaround this limitation for now. it won't be the cleanest code in the world, but you can do it. hint: alias this + returning temporary struct with pointer. and, of course, you can hire Walter or Andrei on a full time to implement the feature you want. otherwise -- this is minor thing, which, nevertheless, require a huge amout of design work. it is unlikely that language devs will drop all other things, and go design and implementing it. and DIP will not help much: W&A still should evaluate it, and it's almost as hard as writing it from scratch. if this minor thing blocks you from using D... alas. otherwise, just make a workaroung and keep going. *eventually* this will be fixed, but you'd better don't wait for it.
Jul 05 2016
next sibling parent reply zodd <zodd maill.com> writes:
On Tuesday, 5 July 2016 at 13:37:50 UTC, ketmar wrote:
 if this minor thing blocks you from using D... alas. otherwise, 
 just make a workaroung and keep going. *eventually* this will 
 be fixed, but you'd better don't wait for it.
No, this issue doesn't block me from using D. I'm asking because I encountered with a few things (like this one), which seems like they're a bit "unfinished". For example: http://forum.dlang.org/post/mailman.1463.1361561853.22503.digitalmars-d learn puremagic.com : "Don't use 'in', because it doesn't mean what it seems to mean, and it's not correctly implemented at the moment." http://forum.dlang.org/post/lgqcjiuigsseoazirkor forum.dlang.org - "cast `shared` away. yes, this is how you supposed to use it now: cast it away." Reading topics like these doesn't add confidence. But don't get me wrong, I don't want to say that "D is unfinished" or "D has a bad design". I don't know it good enough to make such loud statements. I'm just trying to figure out what D is and how can I use it. Answering your other question: I think that production ready language should have a "finished" design and its detailed description (not a basic overview of the features).
Jul 05 2016
parent reply ketmar <ketmar ketmar.no-ip.org> writes:
On Tuesday, 5 July 2016 at 14:07:25 UTC, zodd wrote:
 http://forum.dlang.org/post/mailman.1463.1361561853.22503.digitalmars-d
learn puremagic.com : "Don't use 'in', because it doesn't mean what it seems to
mean, and it's not correctly implemented at the moment."
it is freakin' 2013! ;-)
 http://forum.dlang.org/post/lgqcjiuigsseoazirkor forum.dlang.org - "cast
`shared` away. yes, this is how you supposed to use it now: cast it away."
yes, `shared` need some love. it actually never moved from the concept to something really useful. alas.
 I don't want to say that "D is unfinished"
actually, it is unfinished. ;-) but it already has alot to offer.
 I'm just trying to figure out what D is and how can I use it.
sorry for overreacting. that "D is crap" thread makes me... nervous. ;-)
 Answering your other question: I think that production ready 
 language should have a "finished" design and its detailed 
 description (not a basic overview of the features).
Andrei's book is fairly detailed. And Ali's book is excellent too. it's hard to expect a small, but complete descrion for modern multiparadigm language. ;-) so, my PoV is: yes, D has it's warts, but they are much more tolerable than C++ warts, for example. and D has alot to offer which C++ simply won't be able to offer, ever.
Jul 05 2016
parent reply Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= writes:
On Tuesday, 5 July 2016 at 16:20:52 UTC, ketmar wrote:
 so, my PoV is: yes, D has it's warts, but they are much more 
 tolerable than C++ warts, for example. and D has alot to offer 
 which C++ simply won't be able to offer, ever.
D has «static if», but what else are you thinking of? The only thing I can think of that is hard in C++ is to conditionally remove fields from a struct.
Jul 05 2016
parent reply ketmar <ketmar ketmar.no-ip.org> writes:
On Tuesday, 5 July 2016 at 17:50:46 UTC, Ola Fosheim Grøstad 
wrote:
 On Tuesday, 5 July 2016 at 16:20:52 UTC, ketmar wrote:
 so, my PoV is: yes, D has it's warts, but they are much more 
 tolerable than C++ warts, for example. and D has alot to offer 
 which C++ simply won't be able to offer, ever.
D has «static if», but what else are you thinking of?
C++ templates vs D templates. this alone is enough.
Jul 05 2016
parent reply Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= writes:
On Tuesday, 5 July 2016 at 21:46:19 UTC, ketmar wrote:
 C++ templates vs D templates. this alone is enough.
They are almost the same...
Jul 05 2016
parent reply ketmar <ketmar ketmar.no-ip.org> writes:
On Tuesday, 5 July 2016 at 21:58:39 UTC, Ola Fosheim Grøstad 
wrote:
 On Tuesday, 5 July 2016 at 21:46:19 UTC, ketmar wrote:
 C++ templates vs D templates. this alone is enough.
They are almost the same...
yep. just like C is *almost* the assembler.
Jul 05 2016
parent reply Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= writes:
On Tuesday, 5 July 2016 at 22:03:43 UTC, ketmar wrote:
 On Tuesday, 5 July 2016 at 21:58:39 UTC, Ola Fosheim Grøstad 
 wrote:
 On Tuesday, 5 July 2016 at 21:46:19 UTC, ketmar wrote:
 C++ templates vs D templates. this alone is enough.
They are almost the same...
yep. just like C is *almost* the assembler.
Maybe you could give me an useful example in D that does not involve «static if» or «string mixins» that would be difficult to represent in C++?
Jul 05 2016
parent ketmar <ketmar ketmar.no-ip.org> writes:
On Wednesday, 6 July 2016 at 05:51:04 UTC, Ola Fosheim Grøstad 
wrote:
 Maybe you could give me an useful example in D that does not 
 involve «static if» or «string mixins» that would be difficult 
 to represent in C++?
anything involving templates. c++ template syntax is awful.
Jul 05 2016
prev sibling parent zodd <zodd maill.com> writes:
On Tuesday, 5 July 2016 at 13:37:50 UTC, ketmar wrote:
 you *can* workaround this limitation for now. it won't be the 
 cleanest code in the world, but you can do it. hint: alias this 
 + returning temporary struct with pointer.
Of course, I can. I have been creating a lot of such workarounds with C++ for years. And this is one of the flaws of C++ - for every simple task (like a delegate or properties) you need to create a workaround because C++ standardization Committee thinks that it shouldn't be a part of the language.
Jul 05 2016
prev sibling next sibling parent Steven Schveighoffer <schveiguy yahoo.com> writes:
On 7/5/16 6:52 AM, zodd wrote:

 Is there a chance, that this weird behavior will be fixed in the near
 future? What can I do to help fix it?
Properties do not support read-modify-write operations. You can return a reference, or return a wrapper type to enable the operations you want. D does not support any of the normally-expected property rewrites that many languages do. For example: a.b.c = 5 where b is a property may not do what you expect. It has been suggested in the past to have this behavior, but I doubt it will happen. It's possible to write such mechanisms as a library, but I've never seen someone do it. -Steve
Jul 05 2016
prev sibling parent reply zabruk70 <sorry noem.ail> writes:
On Tuesday, 5 July 2016 at 10:52:10 UTC, zodd wrote:
 Property functions are used wrong by a compiler when it needs
i am sorry for my dumbness, what wrong with this code? import std.stdio; struct A { property ref int value() { return value_; } property void value(int v) { value_ = v; } private: int value_; } int main(string[] args) { A a; a.value = 10; writeln(a.value); a.value += 20; writeln(a.value); return 0; }
Jul 05 2016
next sibling parent "H. S. Teoh via Digitalmars-d-learn" <digitalmars-d-learn puremagic.com> writes:
On Tue, Jul 05, 2016 at 04:11:58PM +0000, zabruk70 via Digitalmars-d-learn
wrote:
 On Tuesday, 5 July 2016 at 10:52:10 UTC, zodd wrote:
 Property functions are used wrong by a compiler when it needs
i am sorry for my dumbness, what wrong with this code? import std.stdio; struct A { property ref int value() { return value_; } property void value(int v) { value_ = v; }
This overload is redundant, now that the first overload is ref.
 private:
 	int value_;
 }
[...] T -- He who does not appreciate the beauty of language is not worthy to bemoan its flaws.
Jul 05 2016
prev sibling next sibling parent ketmar <ketmar ketmar.no-ip.org> writes:
On Tuesday, 5 July 2016 at 16:11:58 UTC, zabruk70 wrote:
 On Tuesday, 5 July 2016 at 10:52:10 UTC, zodd wrote:
 Property functions are used wrong by a compiler when it needs
i am sorry for my dumbness, what wrong with this code?
as OP said, this one won't call setter on "+=" and company.
Jul 05 2016
prev sibling parent reply zodd <zodd maill.com> writes:
So, I've created a simple wrapper template to achieve what I 
want. It reminds me of the C++ - a bunch of additional code to 
solve a simple problem (which shouldn't be an issue at all). I'm 
a newbie in D thus I could do something wrong or nonoptimal. 
Please, criticize my code: http://pastebin.com/XTtXaTAR

A basic idea is to return a wrapper, which can, in turn, call 
getter/setter functions.
Jul 06 2016
parent reply Lodovico Giaretta <lodovico giaretart.net> writes:
On Wednesday, 6 July 2016 at 09:08:11 UTC, zodd wrote:
 So, I've created a simple wrapper template to achieve what I 
 want. It reminds me of the C++ - a bunch of additional code to 
 solve a simple problem (which shouldn't be an issue at all). 
 I'm a newbie in D thus I could do something wrong or 
 nonoptimal. Please, criticize my code: 
 http://pastebin.com/XTtXaTAR

 A basic idea is to return a wrapper, which can, in turn, call 
 getter/setter functions.
Nice work. Personally, I'd do it this way: http://pastebin.com/38n0fEtF This way: - instead of 4 pointers (2 per delegate), the wrapper only contains 1 pointer; - once written, it only requires one line per property to be used; - it creates many more instantiations, which may be a Bad Thing(tm).
Jul 06 2016
parent reply zodd <zodd maill.com> writes:
On Wednesday, 6 July 2016 at 09:48:59 UTC, Lodovico Giaretta 
wrote:
 Nice work.
 Personally, I'd do it this way: http://pastebin.com/38n0fEtF
 This way:
 - instead of 4 pointers (2 per delegate), the wrapper only 
 contains 1 pointer;
 - once written, it only requires one line per property to be 
 used;
 - it creates many more instantiations, which may be a Bad 
 Thing(tm).
Thank you for a great example! D's power still surprises me a lot.
Jul 06 2016
parent ketmar <ketmar ketmar.no-ip.org> writes:
On Wednesday, 6 July 2016 at 10:25:44 UTC, zodd wrote:
 Thank you for a great example! D's power still surprises me a 
 lot.
just be careful to not carry wrapper around for too long, so it won't outlive it's parent. p.s. or this (abomination, i know!). ripped out of one of my monkeycoding projects: import std.stdio; template GST(string fldname, size_t l=__LINE__) { private import std.conv : to; private enum bgsn = "z_buildGST_"~l.to!string; private enum gn = "get_"~fldname; private enum sn = "set_"~fldname; private enum ft = "typeof(cast()"~gn~")"; enum GST = "private alias "~bgsn~"_T = "~ft~";"~ "public property auto "~fldname~"() (in auto ref "~bgsn~"_T v) { "~sn~"(v); return "~bgsn~"; }\n"~ "public property auto "~fldname~"() () const { return "~gn~"; }\n"~ "public property auto "~fldname~"() () { return "~bgsn~"; }\n"~ "private auto "~bgsn~"(T=typeof(this)) () {\n"~ " static struct "~bgsn~"_st {\n"~ " T* _p;\n"~ " alias _g this;\n"~ " auto _g () inout { return _p."~gn~"; }\n"~ " ref auto opAssign() (in auto ref "~bgsn~"_T v) { _p."~sn~"(v); return this; }\n"~ " ref auto opOpAssign(string op) (in auto ref "~bgsn~"_T v) { _p."~sn~"(mixin(`_p."~gn~"`~op~`v`)); return this; }\n"~ " string toString () const { import std.conv : to; return _p."~gn~".to!string; }\n"~ " }\n"~ " return "~bgsn~"_st(&this);\n"~ "}\n"~ ""; } struct Foo { int mVal; this (int n) { mVal = n; } int get_val () const { //import core.stdc.stdio : printf; printf("getter\n"); return mVal+1000; } void set_val (int v) { //import core.stdc.stdio : printf; printf("setter\n"); mVal = v%1000; } mixin(GST!"val"); } void main () { writeln(Foo(42).val = 45); Foo foo; foo.val = 1020; writeln("mv: ", foo.mVal, " : ", foo.val); foo.val += 15; writeln("mv: ", foo.mVal, " : ", foo.val); foo.val--; writeln("mv: ", foo.mVal, " : ", foo.val); int n = (foo.val += 6); writeln("n: ", n); writeln("mv: ", foo.mVal, " : ", foo.val); }
Jul 06 2016