www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Explicitly saying ref or out when invoking a function

reply Ary Borenszweig <ary esperanto.org.ar> writes:
In C# when you define a function that takes an out or ref parameter, 
when invoking that function you must also specify ref or out. For example:

void fun(ref uint x, double y);

uint a = 1;
double b = 2;
fun(ref a, b);

When I first started using C# it really annoyed me that I had to put 
that keyword there just to get my program compiled. "I know what I'm 
doing", I thought. But later, when reading the code, I found it very 
helpful to know that my "a" could be changed when invoking "fun". As 
always, code is read much more times than written, and I think this 
little tips help better understand the code.

What do you think?
Aug 11 2009
next sibling parent Lutger <lutger.blijdestijn gmail.com> writes:
Ary Borenszweig wrote:

 In C# when you define a function that takes an out or ref parameter,
 when invoking that function you must also specify ref or out. For example:
 
 void fun(ref uint x, double y);
 
 uint a = 1;
 double b = 2;
 fun(ref a, b);
 
 When I first started using C# it really annoyed me that I had to put
 that keyword there just to get my program compiled. "I know what I'm
 doing", I thought. But later, when reading the code, I found it very
 helpful to know that my "a" could be changed when invoking "fun". As
 always, code is read much more times than written, and I think this
 little tips help better understand the code.
 
 What do you think?

I'm not sure. However, you could implement something like this in descent without having to type all that or change D ;) Change the color of the parameter or something like that...
Aug 11 2009
prev sibling next sibling parent bearophile <bearophileHUGS lycos.com> writes:
Ary Borenszweig:
 What do you think?

I don't know. It's a different design choice. Generally explicit is better and safer, but I don't know much safer this is. Overall I think the C# choice here is a bit better, but you have to write lot of code before being able to tell C# has chosen for the better. Another similar design choice is that in C# a method that overrides another one must have the attribute "override", while in D it's optional. Now in C#4 you can omit the "ref" in the call point if it's a COM type, this leads to tricks: http://msmvps.com/blogs/jon_skeet/archive/2009/07/07/faking-com-to-fool-the-c-compiler.aspx Bye, bearophile
Aug 11 2009
prev sibling next sibling parent reply BCS <ao pathlink.com> writes:
Reply to Ary,

 In C# when you define a function that takes an out or ref parameter,
 when invoking that function you must also specify ref or out. For
 example:
 
 void fun(ref uint x, double y);
 
 uint a = 1;
 double b = 2;
 fun(ref a, b);
 When I first started using C# it really annoyed me that I had to put
 that keyword there just to get my program compiled. "I know what I'm
 doing", I thought. But later, when reading the code, I found it very
 helpful to know that my "a" could be changed when invoking "fun". As
 always, code is read much more times than written, and I think this
 little tips help better understand the code.
 
 What do you think?
 

It would make template programming harder. template TplFn(alias fn) { void TplFn(T...)(T t) { fn(t); // what if fn has normal, ref and out args? } }
Aug 11 2009
parent bearophile <bearophileHUGS lycos.com> writes:
BCS Wrote:
 It would make template programming harder.
 
 template TplFn(alias fn)
 {
     void TplFn(T...)(T t)
     {
         fn(t); // what if fn has normal, ref and out args?
     }
 }

There's an intermediate solution, to make "ref" optional at the calling site (as in the "override" case). I don't know how much this can improve the situation. Bye, bearophile
Aug 11 2009
prev sibling next sibling parent Edward Diener <eddielee_no_spam_here tropicsoft.com> writes:
Ary Borenszweig wrote:
 In C# when you define a function that takes an out or ref parameter, 
 when invoking that function you must also specify ref or out. For example:
 
 void fun(ref uint x, double y);
 
 uint a = 1;
 double b = 2;
 fun(ref a, b);
 
 When I first started using C# it really annoyed me that I had to put 
 that keyword there just to get my program compiled. "I know what I'm 
 doing", I thought. But later, when reading the code, I found it very 
 helpful to know that my "a" could be changed when invoking "fun". As 
 always, code is read much more times than written, and I think this 
 little tips help better understand the code.
 
 What do you think?

C#'s requirement is just stupid.
Aug 11 2009
prev sibling next sibling parent Denis Koroskin <2korden gmail.com> writes:
Ary Borenszweig Wrote:

 In C# when you define a function that takes an out or ref parameter, 
 when invoking that function you must also specify ref or out. For example:
 
 void fun(ref uint x, double y);
 
 uint a = 1;
 double b = 2;
 fun(ref a, b);
 
 When I first started using C# it really annoyed me that I had to put 
 that keyword there just to get my program compiled. "I know what I'm 
 doing", I thought. But later, when reading the code, I found it very 
 helpful to know that my "a" could be changed when invoking "fun". As 
 always, code is read much more times than written, and I think this 
 little tips help better understand the code.
 
 What do you think?

IIRC, this is no more a case as of C# 3.0
Aug 11 2009
prev sibling next sibling parent Jarrett Billingsley <jarrett.billingsley gmail.com> writes:
On Tue, Aug 11, 2009 at 11:40 AM, Ary Borenszweig<ary esperanto.org.ar> wrote:
 In C# when you define a function that takes an out or ref parameter, when
 invoking that function you must also specify ref or out. For example:

 void fun(ref uint x, double y);

 uint a = 1;
 double b = 2;
 fun(ref a, b);

 When I first started using C# it really annoyed me that I had to put that
 keyword there just to get my program compiled. "I know what I'm doing", I
 thought. But later, when reading the code, I found it very helpful to know
 that my "a" could be changed when invoking "fun". As always, code is read
 much more times than written, and I think this little tips help better
 understand the code.

 What do you think?

I suggested it ages ago and still think it would be a nice requirement.
Aug 11 2009
prev sibling next sibling parent reply Michiel Helvensteijn <m.helvensteijn.remove gmail.com> writes:
Ary Borenszweig wrote:

 In C# when you define a function that takes an out or ref parameter,
 when invoking that function you must also specify ref or out. For example:
 
 void fun(ref uint x, double y);
 
 uint a = 1;
 double b = 2;
 fun(ref a, b);
 
 What do you think?

I see what you mean, however: ----- swap(ref a, ref b); I think that's overly verbose for a call with very descriptive function name to begin with. ----- Perhaps an IDE can use formatting to show you the ref parameters. ----- The designer of the function can always request pointers, so the caller has to explicitly pass addresses. -- Michiel Helvensteijn
Aug 11 2009
next sibling parent Bill Baxter <wbaxter gmail.com> writes:
On Tue, Aug 11, 2009 at 12:47 PM, Michiel
Helvensteijn<m.helvensteijn.remove gmail.com> wrote:
 Ary Borenszweig wrote:

 In C# when you define a function that takes an out or ref parameter,
 when invoking that function you must also specify ref or out. For example:

 void fun(ref uint x, double y);

 uint a = 1;
 double b = 2;
 fun(ref a, b);

 What do you think?

I see what you mean, however: ----- swap(ref a, ref b); I think that's overly verbose for a call with very descriptive function name to begin with.

I don't think that looks so bad. It's not like swap is used in even 1 out of 100 lines of code generally. And it's not an expression either, so it generally is written on a line all by itself.
 -----

 The designer of the function can always request pointers, so the caller has
 to explicitly pass addresses.

But pointers can be null. Refs cannot. That's one big advantage of ref args. Of course if D gets non-nullable pointers... Anyway, I generally like the idea of requiring 'ref' on the call side. But I doubt Walter will go for it. He didn't the last time it was suggested. --bb
Aug 11 2009
prev sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Tue, 11 Aug 2009 15:47:15 -0400, Michiel Helvensteijn  
<m.helvensteijn.remove gmail.com> wrote:

 Ary Borenszweig wrote:

 In C# when you define a function that takes an out or ref parameter,
 when invoking that function you must also specify ref or out. For  
 example:

 void fun(ref uint x, double y);

 uint a = 1;
 double b = 2;
 fun(ref a, b);

 What do you think?

I see what you mean, however: ----- swap(ref a, ref b);

I tend to agree with this, most of the time, your function name hints at what is a reference and what is not. If this is implemented, then a ref const argument should not require a ref keyword to call (since there is no way to change it in the function). One thing about C# is that most everything is pass-by-reference anyways, so the ref and out, keywords are not common. However, in D I think the tendency to lean towards value types, and indicate pass by ref for performance means that code will get a lot uglier if this were to be implemented. This is just a gut feeling, I haven't done a true study. -Steve
Aug 11 2009
prev sibling next sibling parent Bill Baxter <wbaxter gmail.com> writes:
On Tue, Aug 11, 2009 at 1:05 PM, Nick Sabalausky<a a.a> wrote:
 "Ary Borenszweig" <ary esperanto.org.ar> wrote in message
 news:h5s3e9$2kml$1 digitalmars.com...
 In C# when you define a function that takes an out or ref parameter, when
 invoking that function you must also specify ref or out. For example:

 void fun(ref uint x, double y);

 uint a = 1;
 double b = 2;
 fun(ref a, b);

 When I first started using C# it really annoyed me that I had to put that
 keyword there just to get my program compiled. "I know what I'm doing", I
 thought. But later, when reading the code, I found it very helpful to know
 that my "a" could be changed when invoking "fun". As always, code is read
 much more times than written, and I think this little tips help better
 understand the code.

 What do you think?

That's something I've always liked about C# and always wanted in D. Although, what some people have said about just coloring it in an editor is not a bad point (althogh it seems like we may be starting to run out of colors...).

No problem, we can resurrect <BLINK>! --bb
Aug 11 2009
prev sibling next sibling parent "Adam D. Ruppe" <destructionator gmail.com> writes:
On Tue, Aug 11, 2009 at 04:28:06PM -0400, bearophile wrote:
 There's an intermediate solution, to make "ref" optional at the calling site
(as in the "override" case). I don't know how much this can improve the
situation.

That seems to me to defeat the point, since you can't rely on it anymore.
 
 Bye,
 bearophile

-- Adam D. Ruppe http://arsdnet.net
Aug 11 2009
prev sibling next sibling parent reply Jeremie Pelletier <jeremiep gmail.com> writes:
Ary Borenszweig Wrote:

 In C# when you define a function that takes an out or ref parameter, 
 when invoking that function you must also specify ref or out. For example:
 
 void fun(ref uint x, double y);
 
 uint a = 1;
 double b = 2;
 fun(ref a, b);
 
 When I first started using C# it really annoyed me that I had to put 
 that keyword there just to get my program compiled. "I know what I'm 
 doing", I thought. But later, when reading the code, I found it very 
 helpful to know that my "a" could be changed when invoking "fun". As 
 always, code is read much more times than written, and I think this 
 little tips help better understand the code.
 
 What do you think?

I think it's overkill, and it still doesn't say if the ref is const or mutable. Much like in C/C++ when you pass a pointer you dont know if its a const or mutable parameter unless you look at the function declaration. It's especially bad since if you modify the function prototype and change ref, you have all your calls to update too.
Aug 11 2009
parent reply "Lionello Lunesu" <lionello lunesu.remove.com> writes:
"Jeremie Pelletier" <jeremiep gmail.com> wrote in message 
news:h5sl4c$1733$1 digitalmars.com...
 It's especially bad since if you modify the function prototype and change 
 ref, you have all your calls to update too.

That must be the best argument to introduce repeating ref and out! L.
Aug 12 2009
next sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Lionello Lunesu wrote:
 
 "Jeremie Pelletier" <jeremiep gmail.com> wrote in message 
 news:h5sl4c$1733$1 digitalmars.com...
 It's especially bad since if you modify the function prototype and 
 change ref, you have all your calls to update too.

That must be the best argument to introduce repeating ref and out! L.

// untested struct Ref(T) { private T* _data; this(ref T data) { _data = &data; } ref T get() { assert(_data); return *_data; } alias get this; } Ref!(T) byRef(ref T data) { return Ref!(T)(data); } ... void fun(Ref!int rint) { ... } ... int x; fun(byRef(x)); Andrei
Aug 12 2009
next sibling parent Ary Borenszweig <ary esperanto.org.ar> writes:
Andrei Alexandrescu escribió:
 Lionello Lunesu wrote:
 "Jeremie Pelletier" <jeremiep gmail.com> wrote in message 
 news:h5sl4c$1733$1 digitalmars.com...
 It's especially bad since if you modify the function prototype and 
 change ref, you have all your calls to update too.

That must be the best argument to introduce repeating ref and out! L.

// untested struct Ref(T) { private T* _data; this(ref T data) { _data = &data; } ref T get() { assert(_data); return *_data; } alias get this; } Ref!(T) byRef(ref T data) { return Ref!(T)(data); } ... void fun(Ref!int rint) { ... } ... int x; fun(byRef(x)); Andrei

Have you heard about standardization? ;-) But yeah, there's the problem with functions in templated code... I don't know what to do with that...
Aug 12 2009
prev sibling parent reply "Lionello Lunesu" <lionello lunesu.remove.com> writes:
"Andrei Alexandrescu" <SeeWebsiteForEmail erdani.org> wrote in message 
news:h5ttfi$cf3$1 digitalmars.com...
 Lionello Lunesu wrote:
 "Jeremie Pelletier" <jeremiep gmail.com> wrote in message 
 news:h5sl4c$1733$1 digitalmars.com...
 It's especially bad since if you modify the function prototype and 
 change ref, you have all your calls to update too.

That must be the best argument to introduce repeating ref and out! L.

// untested struct Ref(T) { private T* _data; this(ref T data) { _data = &data; } ref T get() { assert(_data); return *_data; } alias get this; } Ref!(T) byRef(ref T data) { return Ref!(T)(data); } ... void fun(Ref!int rint) { ... } ... int x; fun(byRef(x));

Andrei, you bring the compiler vs library discussion to a whole new level :) We can add "ref" to the list of keywords that can be freed up. L.
Aug 12 2009
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Lionello Lunesu wrote:
 
 "Andrei Alexandrescu" <SeeWebsiteForEmail erdani.org> wrote in message 
 news:h5ttfi$cf3$1 digitalmars.com...
 Lionello Lunesu wrote:
 "Jeremie Pelletier" <jeremiep gmail.com> wrote in message 
 news:h5sl4c$1733$1 digitalmars.com...
 It's especially bad since if you modify the function prototype and 
 change ref, you have all your calls to update too.

That must be the best argument to introduce repeating ref and out! L.

// untested struct Ref(T) { private T* _data; this(ref T data) { _data = &data; } ref T get() { assert(_data); return *_data; } alias get this; } Ref!(T) byRef(ref T data) { return Ref!(T)(data); } ... void fun(Ref!int rint) { ... } ... int x; fun(byRef(x));

Andrei, you bring the compiler vs library discussion to a whole new level :) We can add "ref" to the list of keywords that can be freed up.

Good point, but actually ref can't be freed, because it would fall prey to infinite regression: if there was no ref keyword, how would you pass by reference the argument to the byRef function? Andrei
Aug 12 2009
parent "Lionello Lunesu" <lionello lunesu.remove.com> writes:
"Andrei Alexandrescu" <SeeWebsiteForEmail erdani.org> wrote in message 
news:h5vtj8$1l7b$1 digitalmars.com...
 Lionello Lunesu wrote:
 "Andrei Alexandrescu" <SeeWebsiteForEmail erdani.org> wrote in message 
 news:h5ttfi$cf3$1 digitalmars.com...
 Lionello Lunesu wrote:
 "Jeremie Pelletier" <jeremiep gmail.com> wrote in message 
 news:h5sl4c$1733$1 digitalmars.com...
 It's especially bad since if you modify the function prototype and 
 change ref, you have all your calls to update too.

That must be the best argument to introduce repeating ref and out! L.

// untested struct Ref(T) { private T* _data; this(ref T data) { _data = &data; } ref T get() { assert(_data); return *_data; } alias get this; } Ref!(T) byRef(ref T data) { return Ref!(T)(data); } ... void fun(Ref!int rint) { ... } ... int x; fun(byRef(x));

Andrei, you bring the compiler vs library discussion to a whole new level :) We can add "ref" to the list of keywords that can be freed up.

Good point, but actually ref can't be freed, because it would fall prey to infinite regression: if there was no ref keyword, how would you pass by reference the argument to the byRef function?

Uh...... make it an alias parameter and take the address of it? or something... Needs IFTI to work nicely with aliases, not sure if it can be done.. L.
Aug 13 2009
prev sibling parent Ary Borenszweig <ary esperanto.org.ar> writes:
Lionello Lunesu escribió:
 
 "Jeremie Pelletier" <jeremiep gmail.com> wrote in message 
 news:h5sl4c$1733$1 digitalmars.com...
 It's especially bad since if you modify the function prototype and 
 change ref, you have all your calls to update too.

That must be the best argument to introduce repeating ref and out!

No, that's one of the best argument to introduce it. See Nick's reply.
Aug 12 2009
prev sibling next sibling parent Jarrett Billingsley <jarrett.billingsley gmail.com> writes:
On Tue, Aug 11, 2009 at 4:05 PM, Nick Sabalausky<a a.a> wrote:
 Although, what some people have said about just coloring it in an editor is
 not a bad point (althogh it seems like we may be starting to run out of
 colors...).

If your syntax highlighting is using so many colors that you're worried about running out, then your syntax highlighting is using too many colors ;) I never understood why some syntax highlighters make your code look like a goddamned rainbow threw up on it. There are so many colors that they stop meaning anything. Kate's default D highlighting scheme comes to mind as a particularly heinous offender. Do we really need different colors for 1, 0x1, 0b1, 01, and 1.0? They're all numbers. How about different highlighting for *every kind of string literal*?
Aug 11 2009
prev sibling parent soso <vcd9900123 hotmail.com> writes:
Ary Borenszweig Wrote:

 In C# when you define a function that takes an out or ref parameter, 
 when invoking that function you must also specify ref or out. For example:
 
 void fun(ref uint x, double y);
 
 uint a = 1;
 double b = 2;
 fun(ref a, b);
 
 What do you think?

I agree
Aug 11 2009