On Thursday, 1 August 2013 at 23:51:38 UTC, John Colvin wrote:
On Thursday, 1 August 2013 at 22:23:40 UTC, JS wrote:
This is wrong because
(cast(A)b.Y) = 3;
works.
That's an interesting case. cast(A)b.Y) is using the B getter
property, which makes sense as, due to the cast, nothing in B
can be called for the assigment.
So you have (in psuedo-code, all properties expanded as
getY/setY):
b.getY.castToA = 3;
wheras the previous example is:
b.setY(3);
Neither are an int being implicitly converted to an A
b.Y = 3 should do the same as b.a = 3 which should be the same
as b.a.x = 3.
Why that can't work:
struct A
{
double x;
alias x this;
}
struct B
{
private A a;
@property A Y() { importantGetPrep(); return a; }
@property void Y(A v) { importantSetPrep(); a = v; }
}
void main()
{
B b;
b.Y = 3; //cannot be a call to the setter as cannot
convert 3 to A .
//cannot be a call to the getter followed by an
assigment
//as the assignment would then have no effect on
b.a
//due to value semantics.
//cannot be anything else as it would bypass the
//important*etPrep that must be called on all
accesses
//to B.a .
}
Putting functions like important*etPrep in properties are one
of the main reasons why properties are useful, it would be a
very bad idea to let them be circumvented by an implementation
change in an internal struct.
Ok, I don't know why you keep saying 3 cannot be "converted" to
A. Do you
Realize that the ultimate goal is to assign 3 to x? 3 is an int
and x is a double, there is no conversion issues here.
if I do a = 3; b.Y = a; then it is no problem.
The issue is that b.Y wants an A and ignores the alias, I think
this is wrong behavior because when you alias A it is suppose to
act like that type... in this case it doesn't. Simple as that.
I can see why in some cases it is suppose to act the way it does,
e.g., what if B.Y uses other fields of A, you obviously can't use
a int then. If this is the case a run time error or compile time
error should occur.
In any case, I'll just overload the setter to accept double and
be done with it. Arguing whether it is a flaw/limitation in D or
a flaw/limitation in my thinking won't get the behavior I want.
Note, I can just use a setter on double then it will work fine.
This is not the behavior I want though because I breaks the
homogeneity of my code generation.
IMO, if the argument to a setter has an alias this, that type
should also work for the argument. If the body of the setter uses
things not in the aliased type then it it should be an error(in
that case, you should overload the setter).
This way you get the logical behavior expected but can also
handle the more complex case.
code:
struct A { value double; int x; alias this value; }
class B {
@property A prop(A v)
{
A a = new A;
a.value = a.x; // error if v is double and no setter for
double, remove line to make it work.
return a;
}
//@property A prop(double v) { ... } // specialize to prevent
error for doubles
This way for simple properties one gets the expected behavior for
alias this.