Hi all.
Consider following situation. We have a struct named Vector3 it has members
public x, y and z. Also we have a class Camera that has property, for example,
eye. The code is something like this:
struct Vector3
{
float x, y, z;
...
}
class Camera
{
protected Vector3 _eye;
public void eye(Vector3 v)
{
_eye = v;
// do something more
}
public Vector3 eye()
{
return _eye;
}
}
void main()
{
Camera cam = new Camera();
cam.eye.y = 5; // dead line
}
In the code above "dead line" leads to changing y of the copy of the eye. I
think this is not desired behaviour. Something must be done to correct this
language behaviour. I don't know what is the best solution, but the following
IMHO should work:
If we write-access members/props of the struct returned by property then for
writing second, write-property, must be called with parameter that is the
changed copy of the read-property. ahem... I think I explain too complicately
:). In another words, in the example above:
1) cam.eye() returns a copy of original vector _eye
2) 'y' component of this copy is changed to 5
3) write-property came.eye(Vector3) must be called with parameter obtained in
previous action.
Comments?

Check the other thread in this newsgroup about "inout return values". I
guess you'd want something like "inout Vector3 eye() { return eye; }" which
would return a C++-like reference to the struct, instead of a copy.
....This is not yet possible, by the way :-S
L.

Consider following situation. We have a struct named Vector3 it has members
public x, y and z. Also we have a class Camera that has property, for example,
eye.
In the code above "dead line" leads to changing y of the copy of the eye. I
think this is not desired behaviour. Something must be done to correct this
language behaviour.

Until D gets C++-like references, structs won't work for properties...
You need to either make Vector3 a class, or x/y/z into Camera fields ?
--anders

Consider following situation. We have a struct named Vector3 it has members
public x, y and z. Also we have a class Camera that has property, for example,
eye.
In the code above "dead line" leads to changing y of the copy of the eye. I
think this is not desired behaviour. Something must be done to correct this
language behaviour.

Until D gets C++-like references, structs won't work for properties...

I don't want a reference for eye. I want double call of property setter /
getter. First I get a property, then I change it, then I set property with
additional operations coded in eye(Vector3 v)

You need to either make Vector3 a class, or x/y/z into Camera fields ?

First is impossible because of performance issues. Second is very annoying for
example if I'd have not 3 members but 103.

You need to either make Vector3 a class, or x/y/z into Camera fields ?

First is impossible because of performance issues. Second is very annoying for
example if I'd have not 3 members but 103.

--anders

Have you measured the performance issues? I am doing exactly this sort
of coding and I see very small differences in struct/vs class ( at least
compared to other parts of my code which use up more time).
Typically I have 2 needs for Vectors/Points:
1. Equations such as what you posted, these are typically a minute
portion of your running time.
2. Groups of them such as 3d Models where large quantities need to be
manipulated.
For #1, classes work fine. For #2 I simply made a VectorPool class which
handles mass changes to the data and using vertex Arrays easy.
Just my $0.02.

Hi all.
Consider following situation. We have a struct named Vector3 it has
members public x, y and z. Also we have a class Camera that has property,
for example, eye. The code is something like this:
struct Vector3
{
float x, y, z;
...
}
class Camera
{
protected Vector3 _eye;
public void eye(Vector3 v)
{
_eye = v;
// do something more
}
public Vector3 eye()
{
return _eye;
}
}
void main()
{
Camera cam = new Camera();
cam.eye.y = 5; // dead line
}
In the code above "dead line" leads to changing y of the copy of the eye.
I think this is not desired behaviour. Something must be done to correct
this language behaviour. I don't know what is the best solution, but the
following IMHO should work:
If we write-access members/props of the struct returned by property then
for writing second, write-property, must be called with parameter that is
the changed copy of the read-property. ahem... I think I explain too
complicately
:). In another words, in the example above:
1) cam.eye() returns a copy of original vector _eye
2) 'y' component of this copy is changed to 5
3) write-property came.eye(Vector3) must be called with parameter obtained
in previous action.
Comments?

There are some other options besides making language changes:
1) it seems like you want your class to "do something more" when the entire
eye is set but not when just the y component is set. This seems odd to me
so I assume it is an artifact of shortening the example for posting. So my
first reaction is the current behavior is avoiding a bug in your code.
2) returning a pointer from eye() isn't too bad and makes it obvious it is a
reference. The line cam.eye.y would then change the copy owned by the
Camera. But as I said in 1 this seems like it seems like that opens up a
hole to change _eye without doing something more.
3) add properties to just set or translate one component of eye at a time.
For example
void eyeY(float new_y) { _eye.y = new_y; //do something more }
Then instead of cam.eye.y = 5 you have cam.eyeY = 5.
4) don't do anything and just leave the eye setter as the only way to change
_eye. I don't think users will be confused by the behavior of cam.eye.y = 5
-Ben

Hi all.
Consider following situation. We have a struct named Vector3 it has
members public x, y and z. Also we have a class Camera that has property,
for example, eye. The code is something like this:
struct Vector3
{
float x, y, z;
...
}
class Camera
{
protected Vector3 _eye;
public void eye(Vector3 v)
{
_eye = v;
// do something more
}
public Vector3 eye()
{
return _eye;
}
}
void main()
{
Camera cam = new Camera();
cam.eye.y = 5; // dead line
}
In the code above "dead line" leads to changing y of the copy of the eye.
I think this is not desired behaviour. Something must be done to correct
this language behaviour. I don't know what is the best solution, but the
following IMHO should work:
If we write-access members/props of the struct returned by property then
for writing second, write-property, must be called with parameter that is
the changed copy of the read-property. ahem... I think I explain too
complicately
:). In another words, in the example above:
1) cam.eye() returns a copy of original vector _eye
2) 'y' component of this copy is changed to 5
3) write-property came.eye(Vector3) must be called with parameter obtained
in previous action.
Comments?

There are some other options besides making language changes:
1) it seems like you want your class to "do something more" when the entire
eye is set but not when just the y component is set. This seems odd to me
so I assume it is an artifact of shortening the example for posting. So my
first reaction is the current behavior is avoiding a bug in your code.

"do something more" hides the following, for example:
renderSystem.SetViewMatrix( Matrix44.lookAt(_eye, _target, _up) );
you can see that it is necessary to be called even if one component changed.

2) returning a pointer from eye() isn't too bad and makes it obvious it is a
reference. The line cam.eye.y would then change the copy owned by the
Camera. But as I said in 1 this seems like it seems like that opens up a
hole to change _eye without doing something more.

in this case additian action will not take place.

3) add properties to just set or translate one component of eye at a time.
For example
void eyeY(float new_y) { _eye.y = new_y; //do something more }
Then instead of cam.eye.y = 5 you have cam.eyeY = 5.

count of such separate methods will became innumerable at some moment

4) don't do anything and just leave the eye setter as the only way to change
_eye. I don't think users will be confused by the behavior of cam.eye.y = 5

I think expression cam.eye.y = 5 is very natural and so such constructions,
writen because of blunder, can lead to hiden bugs hard to find.

_eye. I don't think users will be confused by the behavior of cam.eye.y =

I think expression cam.eye.y = 5 is very natural and so such

writen because of blunder, can lead to hiden bugs hard to find.

So what about code like
void foo(Vector3 w){w.y = 5;}
...
foo(cam.eye)
Does it modify the original values in cam? I would be surprised if it did -
but then I'm not at all surprised that cam.eye.y changes a copy. Or if you
really want to you can try something like
struct EyeRef {
Vector3* eye;
Camera cam;
...
void y(float new_y) {
eye.y = new_y;
cam.doSomething();
}
Vector3 toValue(){ return *eye; }
}
class Camera {
...
EyeRef eye() {
EyeRef e;
e.cam = this;
e.eye = &_eye;
return e;
}
}
That way cam.eye.y = 5 will set the _eye.y value in cam and call doSomething
in cam afterwards - which I think is what you want to have happen. Writing
cam.eye.toValue will return a copy of the Vector3. Making the language more
complex should be a last resort.

Pointers aren't preferred in D (they're ugly), but they do exist for reasons
aside from legacy compatibility. In this case, simply return a pointer to the
struct you wish to access and all will be well. You won't have to change
anything else, so don't worry about your code bloating up too badly.
Also, if you're exposing a member in this fashion (exposing the whole struct),
you might want to do away with an accessor completely. If there are no in/out
clauses in your accessors, you're not gaining anything by that extra function
call. :)
I, like yourself, first expected structs to be pass-by-reference much like
classes are; obviously, they are pass-by-value. The more D code I wrote, the
more I became to realize that structs are more like heavyweight scalars than
lightweight classes. They still have to obey the copy-on-write rule as other
scalars do.
I think this isn't a flaw in D's design, but rather a deliberate move on
Walter's part to provide compatibility with C. To that end, it lets you do *at
least* as much as C/C++, and then some.
- Pragma at yahoo

I, like yourself, first expected structs to be pass-by-reference much like
classes are; obviously, they are pass-by-value. The more D code I wrote, the
more I became to realize that structs are more like heavyweight scalars than
lightweight classes. They still have to obey the copy-on-write rule as other
scalars do.
I think this isn't a flaw in D's design, but rather a deliberate move on
Walter's part to provide compatibility with C. To that end, it lets you do *at
least* as much as C/C++, and then some.