www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - PROPOSAL: structs be passed by reference...

reply Regan Heath <regan netwin.co.nz> writes:
I thought I'd make this it's own little thread..

I think that structs should be passed by reference, not value, if you want 
to copy-in a struct you can by simply saying...

struct foo {
   int a;
   int b;
   int c;
}

int foobar(foo _a) {
   foo a = _a;
}

I work as a C programmer, so I don't use classes etc, only structs, and I 
pretty much *always* pass a pointer to a struct not a struct itself.

-- 
Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/
May 27 2004
next sibling parent reply J Anderson <REMOVEanderson badmama.com.au> writes:
Regan Heath wrote:

 I thought I'd make this it's own little thread..

 I think that structs should be passed by reference, not value, if you 
 want to copy-in a struct you can by simply saying...

 struct foo {
   int a;
   int b;
   int c;
 }

 int foobar(foo _a) {
   foo a = _a;
 }

 I work as a C programmer, so I don't use classes etc, only structs, 
 and I pretty much *always* pass a pointer to a struct not a struct 
 itself.
If your worried about efficiency, the compiler will optimise the code for the best case. If you want to change the struct, pass it in as inout. -- -Anderson: http://badmama.com.au/~anderson/
May 28 2004
next sibling parent reply imr1984 <imr1984_member pathlink.com> writes:
In article <c96se7$ifr$2 digitaldaemon.com>, J Anderson says...
Regan Heath wrote:

 I thought I'd make this it's own little thread..

 I think that structs should be passed by reference, not value, if you 
 want to copy-in a struct you can by simply saying...

 struct foo {
   int a;
   int b;
   int c;
 }

 int foobar(foo _a) {
   foo a = _a;
 }

 I work as a C programmer, so I don't use classes etc, only structs, 
 and I pretty much *always* pass a pointer to a struct not a struct 
 itself.
If your worried about efficiency, the compiler will optimise the code for the best case. If you want to change the struct, pass it in as inout. -- -Anderson: http://badmama.com.au/~anderson/
I disagree JA. As I said in the other thread on this topic, if you have an exported function that takes a struct param, how can the caller of that function know wether it takes a ref or value, unless its in the prototype? D really needs to nail this one, and I wish Walter would comment on it.
May 28 2004
next sibling parent J Anderson <REMOVEanderson badmama.com.au> writes:
imr1984 wrote:

In article <c96se7$ifr$2 digitaldaemon.com>, J Anderson says...
  

Regan Heath wrote:

    

I thought I'd make this it's own little thread..

I think that structs should be passed by reference, not value, if you 
want to copy-in a struct you can by simply saying...

struct foo {
  int a;
  int b;
  int c;
}

int foobar(foo _a) {
  foo a = _a;
}

I work as a C programmer, so I don't use classes etc, only structs, 
and I pretty much *always* pass a pointer to a struct not a struct 
itself.

      
If your worried about efficiency, the compiler will optimise the code for the best case. If you want to change the struct, pass it in as inout. -- -Anderson: http://badmama.com.au/~anderson/
I disagree JA. As I said in the other thread on this topic, if you have an exported function that takes a struct param, how can the caller of that function know wether it takes a ref or value, unless its in the prototype? D really needs to nail this one, and I wish Walter would comment on it.
When the function is exported it can be labelled with what type of struct it requires. Of course if its a C function then you have no choice. -- -Anderson: http://badmama.com.au/~anderson/
May 28 2004
prev sibling next sibling parent Juanjo =?ISO-8859-15?Q?=C1lvarez?= <juanjuxNO SPAMyahoo.es> writes:
What about a simple, intuitive a logical "refin" keyword?

imr1984 wrote:

 In article <c96se7$ifr$2 digitaldaemon.com>, J Anderson says...
 I disagree JA. As I said in the other thread on this topic, if you have an
 exported function that takes a struct param, how can the caller of that
 function know wether it takes a ref or value, unless its in the prototype?
 D really needs to nail this one, and I wish Walter would comment on it.
May 28 2004
prev sibling parent reply "davepermen" <davepermen hotmail.com> writes:
only c is that dump that it doesn't export the way you have to pass
parameters, and what parameters... even c++ does export the whole info..

"imr1984" <imr1984_member pathlink.com> schrieb im Newsbeitrag
news:c97691$10vd$1 digitaldaemon.com...
 In article <c96se7$ifr$2 digitaldaemon.com>, J Anderson says...
Regan Heath wrote:

 I thought I'd make this it's own little thread..

 I think that structs should be passed by reference, not value, if you
 want to copy-in a struct you can by simply saying...

 struct foo {
   int a;
   int b;
   int c;
 }

 int foobar(foo _a) {
   foo a = _a;
 }

 I work as a C programmer, so I don't use classes etc, only structs,
 and I pretty much *always* pass a pointer to a struct not a struct
 itself.
If your worried about efficiency, the compiler will optimise the code for the best case. If you want to change the struct, pass it in as
inout.
-- 
-Anderson: http://badmama.com.au/~anderson/
I disagree JA. As I said in the other thread on this topic, if you have an exported function that takes a struct param, how can the caller of that
function
 know wether it takes a ref or value, unless its in the prototype? D really
needs
 to nail this one, and I wish Walter would comment on it.
May 28 2004
parent reply Kevin Bealer <Kevin_member pathlink.com> writes:
In article <c9801q$27d1$1 digitaldaemon.com>, davepermen says...
only c is that dump that it doesn't export the way you have to pass
parameters, and what parameters... even c++ does export the whole info..
C has a well documented policy: all arguments are always "in". If the parameter is a pointer, you can modify what it points to, but the argument, the pointer itself, is copied. Another example of the C language philosophy: the programmer understands what the code does but the language just copies bytes. C provides just enough abstraction to hide differences in assembler languages. Whether you passing the data in or out or just preventing optimization of that variable, is not the language's concern (in C). Kevin
May 30 2004
parent "davepermen" <davepermen hotmail.com> writes:
but the caller doesn't KNOW what to pass in, and get back, actually.. (in
linking stage)

"Kevin Bealer" <Kevin_member pathlink.com> schrieb im Newsbeitrag
news:c9c2qf$1vl6$1 digitaldaemon.com...
 In article <c9801q$27d1$1 digitaldaemon.com>, davepermen says...
only c is that dump that it doesn't export the way you have to pass
parameters, and what parameters... even c++ does export the whole info..
C has a well documented policy: all arguments are always "in". If the
parameter
 is a pointer, you can modify what it points to, but the argument, the
pointer
 itself, is copied.  Another example of the C language philosophy: the
programmer
 understands what the code does but the language just copies bytes.  C
provides
 just enough abstraction to hide differences in assembler languages.
Whether you
 passing the data in or out or just preventing optimization of that
variable, is
 not the language's concern (in C).

 Kevin
Jun 03 2004
prev sibling parent reply Regan Heath <regan netwin.co.nz> writes:
On Fri, 28 May 2004 16:15:06 +0800, J Anderson 
<REMOVEanderson badmama.com.au> wrote:
 Regan Heath wrote:

 I thought I'd make this it's own little thread..

 I think that structs should be passed by reference, not value, if you 
 want to copy-in a struct you can by simply saying...

 struct foo {
   int a;
   int b;
   int c;
 }

 int foobar(foo _a) {
   foo a = _a;
 }

 I work as a C programmer, so I don't use classes etc, only structs, and 
 I pretty much *always* pass a pointer to a struct not a struct itself.
If your worried about efficiency, the compiler will optimise the code for the best case. If you want to change the struct, pass it in as inout.
I was worried about efficiency, but also ... so you're saying D will pass my large structs by reference, not value? Ok, next question. If I pass a struct (it gets passed as an 'in' parameter by default) can the function modify it, what happens if it does? From what you say above it can have 2 different effects depending on whether the compiler optimized it or not. I think this is bad. I think 'in' should mean pass by reference AND cannot be modified. The latter causing a compile time error. Regan. -- Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/
May 31 2004
parent reply J Anderson <REMOVEanderson badmama.com.au> writes:
Regan Heath wrote:

 On Fri, 28 May 2004 16:15:06 +0800, J Anderson 
 <REMOVEanderson badmama.com.au> wrote:

 Regan Heath wrote:

 I thought I'd make this it's own little thread..

 I think that structs should be passed by reference, not value, if 
 you want to copy-in a struct you can by simply saying...

 struct foo {
   int a;
   int b;
   int c;
 }

 int foobar(foo _a) {
   foo a = _a;
 }

 I work as a C programmer, so I don't use classes etc, only structs, 
 and I pretty much *always* pass a pointer to a struct not a struct 
 itself.
If your worried about efficiency, the compiler will optimise the code for the best case. If you want to change the struct, pass it in as inout.
I was worried about efficiency, but also ... so you're saying D will pass my large structs by reference, not value? Ok, next question. If I pass a struct (it gets passed as an 'in' parameter by default) can the function modify it, what happens if it does? From what you say above it can have 2 different effects depending on whether the compiler optimized it or not. I think this is bad. I think 'in' should mean pass by reference AND cannot be modified. The latter causing a compile time error. Regan.
The effect shouldn't be visible. If you modify the in struct, then the compiler *must* make a copy of it. However if you don't modify it then the compiler has the choice at compile time. I think about it like this, if the compiler can get away with it without making a side effect then it will. As I said before pass by reference is often very inefficient. If you restrict the compiler to pass-by-reference then your limiting what optimisations the compiler can do. BTW: I don't know how smart the dmd compiler is, at the moment Walter may have used the simplest method and just make a byte copy although he has said that the above does work. -- -Anderson: http://badmama.com.au/~anderson/
Jun 07 2004
parent reply Regan Heath <regan netwin.co.nz> writes:
On Tue, 08 Jun 2004 09:36:04 +0800, J Anderson 
<REMOVEanderson badmama.com.au> wrote:
 Regan Heath wrote:

 On Fri, 28 May 2004 16:15:06 +0800, J Anderson 
 <REMOVEanderson badmama.com.au> wrote:

 Regan Heath wrote:

 I thought I'd make this it's own little thread..

 I think that structs should be passed by reference, not value, if you 
 want to copy-in a struct you can by simply saying...

 struct foo {
   int a;
   int b;
   int c;
 }

 int foobar(foo _a) {
   foo a = _a;
 }

 I work as a C programmer, so I don't use classes etc, only structs, 
 and I pretty much *always* pass a pointer to a struct not a struct 
 itself.
If your worried about efficiency, the compiler will optimise the code for the best case. If you want to change the struct, pass it in as inout.
I was worried about efficiency, but also ... so you're saying D will pass my large structs by reference, not value? Ok, next question. If I pass a struct (it gets passed as an 'in' parameter by default) can the function modify it, what happens if it does? From what you say above it can have 2 different effects depending on whether the compiler optimized it or not. I think this is bad. I think 'in' should mean pass by reference AND cannot be modified. The latter causing a compile time error. Regan.
The effect shouldn't be visible. If you modify the in struct, then the compiler *must* make a copy of it.
Yes. Otherwise you get side effects.
 However if you don't modify it then the compiler has the choice at 
 compile time.  I think about it like this, if the compiler can get away 
 with it without making a side effect then it will.
This idea, and my other to change 'in' to imply "const like" behaviour are linked. I don't think you should be allowed to modify an 'in' parameter without making a copy, after all if you want to modify it, it's either: - an inout incorrectly labelled as an in - only going to be modified for the duration of the function, so why not an explicit copy as shown above. So given the above, it makes no sense for the compiler to give you a copy of a struct, for you to copy it again.
 As I said before pass by reference is often very inefficient.
When? using a very small struct? or something... even then doesn't it have to grab some memory, and copy the contents across? how is that faster than simply pushing an address?
 If you restrict the compiler to pass-by-reference then your limiting 
 what optimisations the compiler can do.
Assuming pass-by-reference can be inefficient, I agree.
 BTW: I don't know how smart the dmd compiler is,  at the moment Walter 
 may have used the simplest method and just make a byte copy although he 
 has said that the above does work.
-- Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/
Jun 07 2004
next sibling parent reply J Anderson <REMOVEanderson badmama.com.au> writes:
Regan Heath wrote:

 Yes. Otherwise you get side effects.

 However if you don't modify it then the compiler has the choice at 
 compile time.  I think about it like this, if the compiler can get 
 away with it without making a side effect then it will.
This idea, and my other to change 'in' to imply "const like" behaviour are linked. I don't think you should be allowed to modify an 'in' parameter without making a copy, after all if you want to modify it, it's either: - an inout incorrectly labelled as an in - only going to be modified for the duration of the function, so why not an explicit copy as shown above.
But the compiler can detect when its const and do it for you automaticly. I think there is a place for const but not here.
 So given the above, it makes no sense for the compiler to give you a 
 copy of a struct, for you to copy it again.
If you explicitly copy it then you are giving the compiler even more work (although the optimiser may be able to remove some of it). That is you now have a reference copy and an array copy.
 As I said before pass by reference is often very inefficient.
When? using a very small struct? or something... even then doesn't it have to grab some memory, and copy the contents across? how is that faster than simply pushing an address?
What is often forgotten with references is that an extra memory location is required and things can't be kept in cache so well. I'm not saying that copying a large struct is a good thing but copying a small structs (32 - 128 bits) can be. It's best to test these theories out (as I have done previously in C++) out. When you assign a reference you have to access the variable though the reference, rather then directly accessing it from the stack (which is on many cpus is automaticly cashed). Quit often what happens is not what you think. Keeping things in cache is a major field of optimisation these days considering its many times faster then ram. You don't want your program sitting around wasting cycles, waiting for some memory to be placed in cache. Best let the compiler make the best choice about how to handle your code for these types of details.
 If you restrict the compiler to pass-by-reference then your limiting 
 what optimisations the compiler can do.
Assuming pass-by-reference can be inefficient, I agree.
I think const should go in somewhere but there still should be an in like operator somewhere. -- -Anderson: http://badmama.com.au/~anderson/
Jun 07 2004
next sibling parent Regan Heath <regan netwin.co.nz> writes:
On Tue, 08 Jun 2004 12:33:11 +0800, J Anderson 
<REMOVEanderson badmama.com.au> wrote:
 Yes. Otherwise you get side effects.

 However if you don't modify it then the compiler has the choice at 
 compile time.  I think about it like this, if the compiler can get 
 away with it without making a side effect then it will.
This idea, and my other to change 'in' to imply "const like" behaviour are linked. I don't think you should be allowed to modify an 'in' parameter without making a copy, after all if you want to modify it, it's either: - an inout incorrectly labelled as an in - only going to be modified for the duration of the function, so why not an explicit copy as shown above.
But the compiler can detect when its const and do it for you automaticly.
Do what? throw a compile time error because you have just tried to modify it? that is what I want.
 I think there is a place for const but not here.
Why not, it seems the perfect place to me. The function designer knows what access they require to the input. That access should never change (if it did the fn would not be the same fn and would cause user code to behave strangely).
 So given the above, it makes no sense for the compiler to give you a 
 copy of a struct, for you to copy it again.
If you explicitly copy it then you are giving the compiler even more work (although the optimiser may be able to remove some of it). That is you now have a reference copy and an array copy.
 As I said before pass by reference is often very inefficient.
When? using a very small struct? or something... even then doesn't it have to grab some memory, and copy the contents across? how is that faster than simply pushing an address?
What is often forgotten with references is that an extra memory location is required and things can't be kept in cache so well. I'm not saying that copying a large struct is a good thing but copying a small structs (32 - 128 bits) can be. It's best to test these theories out (as I have done previously in C++) out. When you assign a reference you have to access the variable though the reference, rather then directly accessing it from the stack (which is on many cpus is automaticly cashed). Quit often what happens is not what you think.
Good points.
 Keeping things in cache is a major field of optimisation these days 
 considering its many times faster then ram. You don't want your program 
 sitting around wasting cycles, waiting for some memory to be placed in 
 cache.  Best let the compiler make the best choice about how to handle 
 your code for these types of details.
I'm not saying I don't want the compiler to manage all that jazz. What I am saying is that I think 'in' should imply const'ness and that I want the most efficient struct passing possible (which I *thought* was by reference - thank you for explaining)
 If you restrict the compiler to pass-by-reference then your limiting 
 what optimisations the compiler can do.
Assuming pass-by-reference can be inefficient, I agree.
I think const should go in somewhere but there still should be an in like operator somewhere.
The current 'in' doesn't do anything, why not change it to do something, like enforce constness. Regan. -- Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/
Jun 07 2004
prev sibling parent reply Norbert Nemec <Norbert.Nemec gmx.de> writes:
J Anderson wrote:

 Best let the compiler make the best choice about how to handle
 your code for these types of details.
This is true in many contexts but not referring to calling conventions: The efficiency does not only depend on the internals of the routine but also on its use. If the compiler does inlining, it can do all the optimizations needed. Otherwise, there is no way to deduct which calling convention would be most efficient in general.
 I think const should go in somewhere but there still should be an in
 like operator somewhere.
What would you consider the difference between a "const" and an "in-like" operator?
Jun 07 2004
parent J Anderson <REMOVEanderson badmama.com.au> writes:
Norbert Nemec wrote:

J Anderson wrote:

  

Best let the compiler make the best choice about how to handle
your code for these types of details.
    
This is true in many contexts but not referring to calling conventions: The efficiency does not only depend on the internals of the routine but also on its use. If the compiler does inlining, it can do all the optimizations needed. Otherwise, there is no way to deduct which calling convention would be most efficient in general.
I think const should go in somewhere but there still should be an in
like operator somewhere.
    
What would you consider the difference between a "const" and an "in-like" operator?
An in-like operator makes a copy and allows you to work on the copy. A const like operator does not allow you to work on the copy (if indeed it is a copy). I think this has been suggested before.... default - const in in - like in now out - like out now inout - like inout now That way you wouldn't have all those consts keywords floating around like Walter hates. It wouldn't be to hard to convert existing programs. -- -Anderson: http://badmama.com.au/~anderson/
Jun 08 2004
prev sibling parent Norbert Nemec <Norbert.Nemec gmx.de> writes:
Regan Heath wrote:

 On Tue, 08 Jun 2004 09:36:04 +0800, J Anderson
 As I said before pass by reference is often very inefficient.
When? using a very small struct? or something... even then doesn't it have to grab some memory, and copy the contents across? how is that faster than simply pushing an address?
It definitely is faster if the data is needed only for the call: ------------ struct A { ... } A produce() { ... } void consume(A value) { ... } consume(produce()); ------------ Unfortunately, this is something the compiler cannot decide by looking only at the routine, but it depends on the usage. Therefore, it should be left to the programmer to specify whether a struct should be passed by value or by reference. My suggestion would be the aforementioned idea: use "in" to indicate pass-by-reference and no modifier to indicate pass-by-value. In the first case, we should forbid writing to the argument alltogether (effectively turning "in" into C++-style "const &"). Making a copy of a pass-by-reference argument never is as efficient as doing pass-by-value in the first place. If the programmer has to do the copying explicitely, it will be more obvious that there is some extra cost. Of course, all of this does not matter if the compiler inlines the function, so it might be just as good to tell the programmer: if you care about performance, enable inlining...
Jun 07 2004
prev sibling parent Andy Friesen <andy ikagames.com> writes:
Regan Heath wrote:
 I thought I'd make this it's own little thread..
 
 I think that structs should be passed by reference, not value, if you 
 want to copy-in a struct you can by simply saying...
 
 struct foo {
   int a;
   int b;
   int c;
 }
 
 int foobar(foo _a) {
   foo a = _a;
 }
 
 I work as a C programmer, so I don't use classes etc, only structs, and 
 I pretty much *always* pass a pointer to a struct not a struct itself.
In the case of extern(D), I agree. In the case of very small structs, the compiler is presumably smart enough to be able to automatically create a copy on the stack, thereby mitigating any speed loss due to an extra dereference. -- andy
May 28 2004