www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - what's the difference between ref and inout in D2?

reply Trass3r <un known.com> writes:
IIRC it was the same in D1, has it changed? If no, what should be used?

This also reminds of another question: why do we have "in" if all  
parameters are in by default?
Mar 12 2010
next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Fri, 12 Mar 2010 15:39:43 -0500, Trass3r <un known.com> wrote:

 IIRC it was the same in D1, has it changed? If no, what should be used?

inout is now completely different from ref. It has been used to implement DIP2 (http://www.prowiki.org/wiki4d/wiki.cgi?action=browse&;id=LanguageDevel/DIPs/D P2&amp;oldid=DiP2). However, the current incarnation is broken, eventually it will work. Use ref wherever you would normally use inout in D1. -Steve
Mar 12 2010
prev sibling next sibling parent reply bearophile <bearophileHUGS lycos.com> writes:
Trass3r:
 why do we have "in" if all  
 parameters are in by default?

If you start performing some experiments on your own you can write a small program like this: // program1 import std.stdio: writeln; void foo(int x, in int y) { x = 1; y = 2; } void main() { int x, y; foo(x, y); writeln(x, " ", y); } The compiler prints an error because y is seen as const. So a better question (I don't know the answer) is: what's the purpose of "in" if now function arguments can be const? A related program: // program2 import std.stdio: writeln; void bar(out int x) { int y = x; // line 4 writeln(y); // prints 0 } void main() { int x = 10; bar(x); writeln(x); // prints 0 } Is this program correct? It compiles and runs, printing 0 two times. I don't like that code. I think it's even worse than a similar C program, where the caller must add a &x, revealing part of how x will be used by the bar() function. I think that in theory the line 4 is an error, because technically y is an output variable, so it's not initialized yet. In practice it's initialized with its init. And I think code like that program2 can easily hide bugs. This shows why built-in tuples are good. Currently there are many holes in D2. If you have answers or comments please let us know. Bye, bearophile
Mar 12 2010
parent reply bearophile <bearophileHUGS lycos.com> writes:
Trass3r:
 This shows why built-in tuples are good.


According to D2 semantics that program2 is correct, because in D you can use variables that are not initialized by the programmers. But the spirit of that program2 is trash anyway, because it reads the value of a variable that's meant to be used as return value only, so it's meant to be written before any read. In a situation like program2 the C# compiler prints an error like: error CS0269: Use of unassigned out parameter `x' Because in C# it is not allowed to use uninitialized variables. This is a so tidy thing (bug probably such tests done by C# compiler forbids some correct spaghetti code that D doesn't forbid. It's hard to find such cases in normal C# programming). So I think 'out' arguments are bug-prone in D. If you have tuples, you can return one of them avoiding the need for 'out' arguments (they can even be removed from the language), so you can avoid some possible bugs. Bye, bearophile
Mar 12 2010
parent bearophile <bearophileHUGS lycos.com> writes:
Trass3r:

And that's good behavior imho.<

Here I prefer the C#/Java compilers, that don't initialize and turn the usage of initialized variables into an error.
(at function entrance I guess).<

Yes. But you have seen in my program2 the variable x is initialized to 10 in the main program. This is a bit bug-prone because such value gets unused. It's like a value written before it's overwritten by its first init value. I think this only happens for 'out' arguments.
I still don't get what you mean. Have an example?<

It's simple. This is a program that you can write now: // program3 import std.stdio: writeln; void spam(out int x, out int y) { x = 10; y = 20; } void main() { int x = 1; int y = 2; spam(x, y); writeln(x, " ", y); // prints 10 20 } Once return values can be tuples too, you can write something like (invented syntax, it's not the best possible syntax): // program4 import std.stdio: writeln; (int, int) spam() { return (10, 20); } void main() { (int x, int y) = spam(x, y); writeln(x); } Here there is no risk of preassigning the values 1 and 2 that get lost, there is no risk of forgetting to add a 'out' attribute, etc. It's less bug-prone (but the programmer has to take care of using the correct order in the tuple, because they are not named. Fields in a Phobos2 Tuple can be named). Using a Record/record of my dlibs1 (similar to Tuple of Phobos2) that's essentially a smarter struct today you can write something like this in D1 too: // program5 import std.stdio: writeln; Record!(int, int) spam() { return record(10, 20) } void main() { int x, y; derecord(spam(x, y), x, y); writeln(x); } Or in D2: // program6 import std.stdio: writeln; auto spam() { return record(10, 20); } void main() { int x, y; derecord(spam(x, y), x, y); writeln(x); } In D2 you may even be able to write: // program7 import std.stdio: writeln; auto spam() { return record(10, 20); } void main() { int x, y; derecord(x, y) = spam(x, y); writeln(x); } But it's not good. And something like this is not nice looking at all: // program8 import std.stdio: writeln; auto spam() { return record(10, 20); } void main() { mixin(Derecord!("x", int, "y", int, spam(x, y))); } Bye, bearophile7
Mar 12 2010
prev sibling next sibling parent Trass3r <un known.com> writes:
 So a better question (I don't know the answer) is: what's the purpose of  
 "in" if now function arguments can be const?

 Is this program correct? It compiles and runs, printing 0 two times.

their init as you said.
 This shows why built-in tuples are good.

Mar 12 2010
prev sibling next sibling parent Trass3r <un known.com> writes:
 According to D2 semantics that program2 is correct, because in D you can  
 use variables that are not initialized by the programmers.
 ...
 Because in C# it is not allowed to use uninitialized variables.

D's general approach is to initialize every variable and only allow unintialized ones with explicit "= void" And that's good behavior imho. So "out parameters are set to the default initializer for the type of it" (at function entrance I guess).
 So I think 'out' arguments are bug-prone in D. If you have tuples, you  
 can return one of them avoiding the need for 'out' arguments

I still don't get what you mean. Have an example?
Mar 12 2010
prev sibling parent Trass3r <un known.com> writes:
 The compiler prints an error because y is seen as const. So a better  
 question (I don't know the answer) is: what's the purpose of "in" if now  
 function arguments can be const?

Had another look. "If no storage class is specified, the parameter becomes a mutable copy of its argument" "The in storage class is equivalent to const scope." But what is scope in this context?
Mar 13 2010