January 17, 2017
On 1/17/17 9:32 AM, Eugene Wissner wrote:
> Ah, well thanks. I don't think it makes much sense since it would be
> easier to write a complete setter if the user needs extra checks.
> Accessors are there only for the generation of the standard methods,
> that just get or set some object property.

Hmmm... that's a bit of a bummer because it helps only the degenerate case (accessors are there as placeholders for future extensions, and otherwise offer no protection whatsoever compared to a public value). The question would be then what would be use cases for the accessors. Predicated setters are not just a random thing one might want out of many possibilities, it's a frequent pattern. -- Andrei
January 17, 2017
On Tuesday, 17 January 2017 at 09:17:56 UTC, Andrei Alexandrescu wrote:
> On 1/17/17 9:32 AM, Eugene Wissner wrote:
>> Ah, well thanks. I don't think it makes much sense since it would be
>> easier to write a complete setter if the user needs extra checks.
>> Accessors are there only for the generation of the standard methods,
>> that just get or set some object property.
>
> Hmmm... that's a bit of a bummer because it helps only the degenerate case (accessors are there as placeholders for future extensions, and otherwise offer no protection whatsoever compared to a public value). The question would be then what would be use cases for the accessors. Predicated setters are not just a random thing one might want out of many possibilities, it's a frequent pattern. -- Andrei

Given that D supports class invariants, is there a real need for predicated setters?
January 17, 2017
On 1/17/17 12:08 PM, Mark wrote:
> On Tuesday, 17 January 2017 at 09:17:56 UTC, Andrei Alexandrescu wrote:
>> On 1/17/17 9:32 AM, Eugene Wissner wrote:
>>> Ah, well thanks. I don't think it makes much sense since it would be
>>> easier to write a complete setter if the user needs extra checks.
>>> Accessors are there only for the generation of the standard methods,
>>> that just get or set some object property.
>>
>> Hmmm... that's a bit of a bummer because it helps only the degenerate
>> case (accessors are there as placeholders for future extensions, and
>> otherwise offer no protection whatsoever compared to a public value).
>> The question would be then what would be use cases for the accessors.
>> Predicated setters are not just a random thing one might want out of
>> many possibilities, it's a frequent pattern. -- Andrei
>
> Given that D supports class invariants, is there a real need for
> predicated setters?

The invariant is evaluated after the setter has taken place, i.e. after the object has been corrupted. The setter guard prevents corruption from happening.  -- Andrei
January 18, 2017
On Tuesday, 17 January 2017 at 15:59:26 UTC, Andrei Alexandrescu wrote:
> On 1/17/17 12:08 PM, Mark wrote:
>> On Tuesday, 17 January 2017 at 09:17:56 UTC, Andrei Alexandrescu wrote:
>>> On 1/17/17 9:32 AM, Eugene Wissner wrote:
>>>> Ah, well thanks. I don't think it makes much sense since it would be
>>>> easier to write a complete setter if the user needs extra checks.
>>>> Accessors are there only for the generation of the standard methods,
>>>> that just get or set some object property.
>>>
>>> Hmmm... that's a bit of a bummer because it helps only the degenerate
>>> case (accessors are there as placeholders for future extensions, and
>>> otherwise offer no protection whatsoever compared to a public value).
>>> The question would be then what would be use cases for the accessors.
>>> Predicated setters are not just a random thing one might want out of
>>> many possibilities, it's a frequent pattern. -- Andrei
>>
>> Given that D supports class invariants, is there a real need for
>> predicated setters?
>
> The invariant is evaluated after the setter has taken place, i.e. after the object has been corrupted. The setter guard prevents corruption from happening.  -- Andrei

I see. Is there a way to call invariant() of a class/struct directly? That would obviate the need for a particular predicate (copy the class state, run the setter, check if invariants are satisfied and restore previous state if they aren't).
January 18, 2017
On Wednesday, 18 January 2017 at 15:29:43 UTC, Mark wrote:
> On Tuesday, 17 January 2017 at 15:59:26 UTC, Andrei Alexandrescu wrote:
>> On 1/17/17 12:08 PM, Mark wrote:
>>> On Tuesday, 17 January 2017 at 09:17:56 UTC, Andrei Alexandrescu wrote:
>>>> [...]
>>>
>>> Given that D supports class invariants, is there a real need for
>>> predicated setters?
>>
>> The invariant is evaluated after the setter has taken place, i.e. after the object has been corrupted. The setter guard prevents corruption from happening.  -- Andrei
>
> I see. Is there a way to call invariant() of a class/struct directly? That would obviate the need for a particular predicate (copy the class state, run the setter, check if invariants are satisfied and restore previous state if they aren't).

You can call invariant directly with `assert(this);` IIRC.
January 18, 2017
On 1/18/17 5:29 PM, Mark wrote:
> I see. Is there a way to call invariant() of a class/struct directly?
> That would obviate the need for a particular predicate (copy the class
> state, run the setter, check if invariants are satisfied and restore
> previous state if they aren't).

It seems painfully obvious the right way is a guarded assignment and anything else would be a more or less painful workaround. -- Andrei
January 19, 2017
On Wednesday, 18 January 2017 at 21:57:42 UTC, Andrei Alexandrescu wrote:
> On 1/18/17 5:29 PM, Mark wrote:
>> I see. Is there a way to call invariant() of a class/struct directly?
>> That would obviate the need for a particular predicate (copy the class
>> state, run the setter, check if invariants are satisfied and restore
>> previous state if they aren't).
>
> It seems painfully obvious the right way is a guarded assignment and anything else would be a more or less painful workaround. -- Andrei

I agree. I'm just a bit unsettled by the slight code duplication that would ensue.
June 13, 2017
On Sunday, 11 December 2016 at 02:17:18 UTC, Mike Parker wrote:
>
> What are properties if not "getters" and "setters"? From the original post: "It would generate 2 methods "num": one to set num_ and one to get its value."
>
> Two methods named "num". No "get" or "set" in sight.

Sorry to bump, but it also isn't hard to use mixins to write more generic get/set.

import std.stdio : writeln;

struct Foo
{
	private int a;
	private int b;
	
	void set(string variable)(int x) @property
	{
		mixin(variable ~ " = x;");
	}
	
	int get(string variable)() @property
	{
		return mixin(variable);
	}
}

void main()
{
	Foo foo;
	foo.set!("a")(1);
	foo.set!("b")(2);
	writeln(foo.get!("a"));
	writeln(foo.get!("b"));
}
June 13, 2017
On Tuesday, 13 June 2017 at 19:31:28 UTC, jmh530 wrote:
> On Sunday, 11 December 2016 at 02:17:18 UTC, Mike Parker wrote:
>>
>> What are properties if not "getters" and "setters"? From the original post: "It would generate 2 methods "num": one to set num_ and one to get its value."
>>
>> Two methods named "num". No "get" or "set" in sight.
>
> Sorry to bump, but it also isn't hard to use mixins to write more generic get/set.
>
> import std.stdio : writeln;
>
> struct Foo
> {
> 	private int a;
> 	private int b;
> 	
> 	void set(string variable)(int x) @property
> 	{
> 		mixin(variable ~ " = x;");
> 	}
> 	
> 	int get(string variable)() @property
> 	{
> 		return mixin(variable);
> 	}
> }
>
> void main()
> {
> 	Foo foo;
> 	foo.set!("a")(1);
> 	foo.set!("b")(2);
> 	writeln(foo.get!("a"));
> 	writeln(foo.get!("b"));
> }

I suppose the errors will be more cryptic, since you don't check if the string referers to an existing member.

You provide only get/set that return by value. So you may need to generate getters/setters for const values, for ref values, for const ref values... And it would result in much more code for every object.
June 13, 2017
On Tuesday, 13 June 2017 at 20:31:25 UTC, Eugene Wissner wrote:
>
> I suppose the errors will be more cryptic, since you don't check if the string referers to an existing member.
>
> You provide only get/set that return by value. So you may need to generate getters/setters for const values, for ref values, for const ref values... And it would result in much more code for every object.

Fair point. I just was playing around with it today and was like, oh that's pretty easy. It was only when I was trying to see if anyone else had done anything like this that I came across your project.