Thread overview
ref vs out.
Feb 14, 2011
Charles McAnany
Feb 14, 2011
Jesse Phillips
Feb 14, 2011
Stanislav Blinov
February 14, 2011
Hi, all. So I'm new to this whole contract thing. (I'm coming from C and Java.) I got the impression that using foo(out arg) means that arg is given its default value, but other than that it's just like ref. So, here's the basic code I have thus far.

01 import std.random:Random;
02 import std.container:heapify;
03 Random gen;
04 void main(){
05      auto start = new int[n];
06      randomize(start);
07      auto theHeap = heapify(start);
08      int temp = theHeap.front;
09 }
10 void randomize(ref int[] arr){
11      foreach(ref i; arr){
12           i = gen.front % 10000;
13           gen.popFront;
14      }
15 }

This compiles and runs.
However, if I switch the method signature to randomize(out int[] arr)
I get
object.Exception@C:\D\dmd2\windows\bin\..\..\src\phobos\std\container.d(2533):
Enforcement failed
(This is a run-time error, it compiles fine.)
What's really perplexing is that the problem comes from line 8.
If I comment out 8, then there's no enforcement error.

If it helps, container.d includes
2531     @property ElementType!Store front()
2532    {
2533        enforce(!empty);
2534        return _store.front;
2545    }

Thanks,
Charles
February 14, 2011
Charles McAnany Wrote:

> Hi, all. So I'm new to this whole contract thing. (I'm coming from C and Java.) I got the impression that using foo(out arg) means that arg is given its default value, but other than that it's just like ref. So, here's the basic code I have thus far.

The init value for a dynamic array is null. Thus you have an empty array when you change to 'out', and you assign nothing into it.
February 14, 2011
14.02.2011 18:06, Charles McAnany пишет:
> Hi, all. So I'm new to this whole contract thing. (I'm coming from C and Java.)
> I got the impression that using foo(out arg) means that arg is given its
> default value, but other than that it's just like ref. So, here's the basic
> code I have thus far.
>
> 01 import std.random:Random;
> 02 import std.container:heapify;
> 03 Random gen;
> 04 void main(){
> 05      auto start = new int[n];
> 06      randomize(start);
> 07      auto theHeap = heapify(start);
> 08      int temp = theHeap.front;
> 09 }
> 10 void randomize(ref int[] arr){
> 11      foreach(ref i; arr){
> 12           i = gen.front % 10000;
> 13           gen.popFront;
> 14      }
> 15 }
>
> This compiles and runs.
> However, if I switch the method signature to randomize(out int[] arr)
> I get
> object.Exception@C:\D\dmd2\windows\bin\..\..\src\phobos\std\container.d(2533):
> Enforcement failed
> (This is a run-time error, it compiles fine.)
> What's really perplexing is that the problem comes from line 8.
> If I comment out 8, then there's no enforcement error.
>
> If it helps, container.d includes
> 2531     @property ElementType!Store front()
> 2532    {
> 2533        enforce(!empty);
> 2534        return _store.front;
> 2545    }
>
> Thanks,
> Charles

There's nothing perplexing at all - the default initializer for a dynamic array is an empty dynamic array :) So, because it is indeed a pass-by-reference with an enforced initialization, 'start' references an empty slice after randomize() call, hence the enforcement failure.