Returning a struct by reference

2009-03-21 Thread Simon TRENY
Hi there!

I'm quite new at D and I'm still just playing with it, but there is a thing 
that I find currently missing. Sometimes, I'd like to be able to return a 
struct by reference and not by value. For example, in the following example:

struct Position {
   float x;
   float y;
}

class Object {
   private Position m_position;

   public Position position() {
  return m_position;
   }
}

I'd like to be able to write things like this: myObject.position.x = 43 to 
actually change the position of the object. But right now, since position is 
a struct, it is returned by value and not by reference, and then the previous 
instruction won't change the position of the object, but it will work on a copy 
of the position field.


Here is the solutions that I can see to this problem:

- Returning a pointer to the position: public Position *position() { ... }, 
but I'd like to keep my code as free from pointers as possible.
 - Make Position a class and not a struct. That could be a solution, but 
then, when I'll do things like Position pos = object.position; pos.x = 43;, 
it will effectively change the position of the object, which I wouldn't like 
with this syntax.

Actually, I'd like to be able to do a thing like this:
   public ref Position position() {
  return m_position;
   }
which would be the equivalent form to passing structs by reference in a 
parameter.

Is there a way to do this in D?

Regards,
Simon



Re: Returning a struct by reference

2009-03-21 Thread grauzone

Simon TRENY wrote:

Hi there!

I'm quite new at D and I'm still just playing with it, but there is a thing 
that I find currently missing. Sometimes, I'd like to be able to return a 
struct by reference and not by value. For example, in the following example:

struct Position {
   float x;
   float y;
}

class Object {
   private Position m_position;

   public Position position() {
  return m_position;
   }
}

I'd like to be able to write things like this: myObject.position.x = 43 to actually 
change the position of the object. But right now, since position is a struct, 
it is returned by value and not by reference, and then the previous instruction won't 
change the position of the object, but it will work on a copy of the position field.


Here is the solutions that I can see to this problem:

- Returning a pointer to the position: public Position *position() { ... }, 
but I'd like to keep my code as free from pointers as possible.
 - Make Position a class and not a struct. That could be a solution, but then, when 
I'll do things like Position pos = object.position; pos.x = 43;, it will effectively 
change the position of the object, which I wouldn't like with this syntax.

Actually, I'd like to be able to do a thing like this:
   public ref Position position() {
  return m_position;
   }
which would be the equivalent form to passing structs by reference in a 
parameter.

Is there a way to do this in D?


Yes. Make the variable public.

class Object {
Position position;
}

This code is even simpler than your's above. Incredible, isn't it?


Regards,
Simon



Re: Returning a struct by reference

2009-03-21 Thread Daniel Keep


Simon TRENY wrote:
 Ok, but then, what if I'd like to make the variable read-only? i.e. 
 preventing the user from writing things like this:
 myObject.position = pos2;
 

So... you're rejecting a solution on the basis that it prevents you from
doing the exact opposite of what you want to do?

*boggle*

  -- Daniel


Re: Returning a struct by reference

2009-03-21 Thread Simon TRENY
grauzone Wrote:

 Simon TRENY wrote:
  Hi there!
  
  I'm quite new at D and I'm still just playing with it, but there is a thing 
  that I find currently missing. Sometimes, I'd like to be able to return a 
  struct by reference and not by value. For example, in the following example:
  
  struct Position {
 float x;
 float y;
  }
  
  class Object {
 private Position m_position;
  
 public Position position() {
return m_position;
 }
  }
  
  I'd like to be able to write things like this: myObject.position.x = 43 to 
  actually change the position of the object. But right now, since position 
  is a struct, it is returned by value and not by reference, and then the 
  previous instruction won't change the position of the object, but it will 
  work on a copy of the position field.
  
  
  Here is the solutions that I can see to this problem:
  
  - Returning a pointer to the position: public Position *position() { ... 
  }, but I'd like to keep my code as free from pointers as possible.
   - Make Position a class and not a struct. That could be a solution, but 
  then, when I'll do things like Position pos = object.position; pos.x = 
  43;, it will effectively change the position of the object, which I 
  wouldn't like with this syntax.
  
  Actually, I'd like to be able to do a thing like this:
 public ref Position position() {
return m_position;
 }
  which would be the equivalent form to passing structs by reference in a 
  parameter.
  
  Is there a way to do this in D?
 
 Yes. Make the variable public.
 
 class Object {
   Position position;
 }
 
 This code is even simpler than your's above. Incredible, isn't it?

Ok, but then, what if I'd like to make the variable read-only? i.e. 
preventing the user from writing things like this:
myObject.position = pos2;

 
  Regards,
  Simon
  



Re: Returning a struct by reference

2009-03-21 Thread grauzone

Simon TRENY wrote:

grauzone Wrote:


Simon TRENY wrote:

Hi there!

I'm quite new at D and I'm still just playing with it, but there is a thing 
that I find currently missing. Sometimes, I'd like to be able to return a 
struct by reference and not by value. For example, in the following example:

struct Position {
   float x;
   float y;
}

class Object {
   private Position m_position;

   public Position position() {
  return m_position;
   }
}

I'd like to be able to write things like this: myObject.position.x = 43 to actually 
change the position of the object. But right now, since position is a struct, 
it is returned by value and not by reference, and then the previous instruction won't 
change the position of the object, but it will work on a copy of the position field.


Here is the solutions that I can see to this problem:

- Returning a pointer to the position: public Position *position() { ... }, 
but I'd like to keep my code as free from pointers as possible.
 - Make Position a class and not a struct. That could be a solution, but then, when 
I'll do things like Position pos = object.position; pos.x = 43;, it will effectively 
change the position of the object, which I wouldn't like with this syntax.

Actually, I'd like to be able to do a thing like this:
   public ref Position position() {
  return m_position;
   }
which would be the equivalent form to passing structs by reference in a 
parameter.

Is there a way to do this in D?

Yes. Make the variable public.

class Object {
Position position;
}

This code is even simpler than your's above. Incredible, isn't it?


Ok, but then, what if I'd like to make the variable read-only? i.e. 
preventing the user from writing things like this:
myObject.position = pos2;


Then you write a getter that simply returns the field by value.

The D compiler will (hopefully) inline the getter function, so there 
shouldn't be a disadvantage in performance.


Note: I think D2.0 wants to introduce ref-returns at some point in the 
future.



Regards,
Simon





Re: Returning a struct by reference

2009-03-21 Thread Simon TRENY
Daniel Keep Wrote:

 
 
 Simon TRENY wrote:
  Ok, but then, what if I'd like to make the variable read-only? i.e. 
  preventing the user from writing things like this:
  myObject.position = pos2;
  
 
 So... you're rejecting a solution on the basis that it prevents you from
 doing the exact opposite of what you want to do?
 
 *boggle*
 
   -- Daniel

Here is a complete example of what I'd like to achieve:
struct Position {
   private float m_x;
   private float m_y;

   public float x() {
  return m_x;
   }

   public void x(float x) {
  m_x = x;
  EmitSignal(changed);
   }

   public float y() {
  return m_y;
   }

   public void y(float y) {
  m_y = y;
  EmitSignal(changed);
   }
}

class Object {
   private Position m_position;

   public this() {
  m_position.CallOnSignal(changed, onPositionChanged);
   }

   //This syntax is not working
   public ref Position position() {
  return m_position;
   }

   public void onPositionChanged() {
  writeln(Position Changed!!);
   }
}

With this fictional code, I could write things like:
object.position.x = 14; and the object will be aware that its position has 
changed.

Making the position-variable public will lead the user to be able to do 
things like this:
object.position = pos2; and then, the object won't be aware that its position 
has changed. And this is a problem for me.

I hope it's clearer now


Re: Returning a struct by reference

2009-03-21 Thread Simon TRENY
grauzone Wrote:

 Simon TRENY wrote:
  grauzone Wrote:
  
  Simon TRENY wrote:
  Hi there!
 
  I'm quite new at D and I'm still just playing with it, but there is a 
  thing that I find currently missing. Sometimes, I'd like to be able to 
  return a struct by reference and not by value. For example, in the 
  following example:
 
  struct Position {
 float x;
 float y;
  }
 
  class Object {
 private Position m_position;
 
 public Position position() {
return m_position;
 }
  }
 
  I'd like to be able to write things like this: myObject.position.x = 43 
  to actually change the position of the object. But right now, since 
  position is a struct, it is returned by value and not by reference, and 
  then the previous instruction won't change the position of the object, 
  but it will work on a copy of the position field.
 
 
  Here is the solutions that I can see to this problem:
 
  - Returning a pointer to the position: public Position *position() { ... 
  }, but I'd like to keep my code as free from pointers as possible.
   - Make Position a class and not a struct. That could be a solution, 
  but then, when I'll do things like Position pos = object.position; pos.x 
  = 43;, it will effectively change the position of the object, which I 
  wouldn't like with this syntax.
 
  Actually, I'd like to be able to do a thing like this:
 public ref Position position() {
return m_position;
 }
  which would be the equivalent form to passing structs by reference in a 
  parameter.
 
  Is there a way to do this in D?
  Yes. Make the variable public.
 
  class Object {
 Position position;
  }
 
  This code is even simpler than your's above. Incredible, isn't it?
  
  Ok, but then, what if I'd like to make the variable read-only? i.e. 
  preventing the user from writing things like this:
  myObject.position = pos2;
 
 Then you write a getter that simply returns the field by value.
 
 The D compiler will (hopefully) inline the getter function, so there 
 shouldn't be a disadvantage in performance.

If I add a getter-property that returns the field by value, the following 
instruction object.position.x = 12; won't modify the position of the object, 
but will only modify the returned copy of the position, right?
That's actually why I'd like to have a getter that returns the field by 
reference and not by value.

 
 Note: I think D2.0 wants to introduce ref-returns at some point in the 
 future.
 
  Regards,
  Simon
 
  



Re: Returning a struct by reference

2009-03-21 Thread Sergey Gromov
Sat, 21 Mar 2009 09:55:13 -0400, Simon TRENY wrote:

//This syntax is not working
public ref Position position() {
   return m_position;
}

D2 supports this.
D1 won't, ever.  I think.


Re: Returning a struct by reference

2009-03-21 Thread grauzone

Simon TRENY wrote:

Daniel Keep Wrote:



Simon TRENY wrote:

Ok, but then, what if I'd like to make the variable read-only? i.e. 
preventing the user from writing things like this:
myObject.position = pos2;


So... you're rejecting a solution on the basis that it prevents you from
doing the exact opposite of what you want to do?

*boggle*

  -- Daniel


Here is a complete example of what I'd like to achieve:
struct Position {
   private float m_x;
   private float m_y;

   public float x() {
  return m_x;
   }

   public void x(float x) {
  m_x = x;
  EmitSignal(changed);
   }

   public float y() {
  return m_y;
   }

   public void y(float y) {
  m_y = y;
  EmitSignal(changed);
   }
}

class Object {
   private Position m_position;

   public this() {
  m_position.CallOnSignal(changed, onPositionChanged);
   }

   //This syntax is not working
   public ref Position position() {
  return m_position;
   }

   public void onPositionChanged() {
  writeln(Position Changed!!);
   }
}

With this fictional code, I could write things like:
object.position.x = 14; and the object will be aware that its position has 
changed.

Making the position-variable public will lead the user to be able to do 
things like this:
object.position = pos2; and then, the object won't be aware that its position 
has changed. And this is a problem for me.


But if position is returned as ref, this still could happen. The 
returned value is still assignable, and because it's a ref, overwriting 
it is like overwriting m_position directly. As far as I see, your 
position()-getter just emulates a public field. Including overwriting by 
assignment.



Now D2.0 has const. If position() would return a const object, this kind 
of unwanted overwriting couldn't happen. This improves correctness, 
because uncatched changes or changes to temporaries can't happen. But 
then again, the setters in the Position struct wouldn't work, because 
the struct is const (as far as I understand the const system). This 
means returning the field as a const ref wouldn't help.



Also, how is this EmitSignal() working? What happens if you write:

Position p = object.position;
p.x = 14; //EmitSignal() calls what?

p is simply a bit-copy of the struct returned by the getter, and 
EmitSignal() has no way to check if it's still supposed to notify class 
Object. (All solutions I can come up with sound really hairy and hackish.)


Maybe you're better off with Position as a class instead of a struct. 
Even when you use D2.0's const/opAssign/copy-ctor/post-blit/ref-return 
features.


Looking forward to the replies pointing out that D2.0 actually allows to 
implement exactly what you want, and how this is done.



I hope it's clearer now


Re: Returning a struct by reference

2009-03-21 Thread BCS

Hello Simon,


If I add a getter-property that returns the field by value, the
following instruction object.position.x = 12; won't modify the
position of the object, but will only modify the returned copy of the
position, right?

That's actually why I'd like to have a getter that returns the field
by reference and not by value.




That is correct. Reference returns are on the todo list. For now this Hack 
should work.



struct S { float x; float y; }


class C
{
   S s

   class C_S { void x(float v){ s.x=v; } void y(float v){ s.y=v; } }

   C_S pos() { return new C_S(); }
}