[Issue 8026] Fix or disallow randomShuffle() on fixed-sized arrays

d-bugmail at puremagic.com d-bugmail at puremagic.com
Fri May 11 15:38:03 PDT 2012


http://d.puremagic.com/issues/show_bug.cgi?id=8026



--- Comment #4 from Jonathan M Davis <jmdavisProg at gmx.com> 2012-05-11 15:39:26 PDT ---
http://stackoverflow.com/questions/8873265/is-a-static-array-a-forward-range

A static array is a value type. It owns its own memory. It's a container, not a
range.

A dynamic array is a reference type. It does _not_ own its own memory (the
runtime does). It is _not_ a container. It _is_ a range.

If I do

int[] func()
{
    auto arr = [1, 2, 3, 4, 5];
    return find(arr, 3);
}

there is _zero_ difference between passing arr and passing arr[]. In either
case, you're slicing the whole array. And the array being returned is a slice
of arr ([3, 4, 5] to be exact) whose memory is on the heap, owned by the
runtime.

If I do

int[] func()
{
    int[5] arr = [1, 2, 3, 4, 5];
    return find(arr[], 3);
}

I've now allocated a static array _on the stack_. Passing arr to a function
would copy it (since it's a value type). Passing arr[] to a function would
slice it, which means passing a reference to the static array. Now look at what
func returns. It's returning a slice of arr, which is a _local variable_ _on
the stack_. What you've done is the equivalent of

int* func()
{
    int i;
    return &i;
}

You've returned a reference/pointer to a local variable which no longer exists.
Bad things will happen if you do this. So, the semantics of dealing with
dynamic and static arrays are _very_ different. Slicing a static array in the
wrong place can lead to major bugs, whereas slicing a dynamic array is
perfectly safe.


Now, as to range-based functions in general. They're templated functions. That
means that they use IFTI (implicit function template instantiation) - i.e. it
infers the type. So, if you have

auto func(T)(T foo)
{
    ...
}

int[] dArr;
int[5] sArr;

foo(dArr);
foo(sArr);

T is going to be inferred as the _exact type_ that you pass in. So, in the
first case, func gets instantiated as

auto func(int[] foo)
{
    ...
}

whereas in the second, it gets instantiated as

auto func(int[5] foo)
{
    ...
}

int[] is a range, int[5] is not. So, if func is a range-based function, it
should have a template constraint on it, and the static array will fail that
constraint.

auto func(T)(T foo)
    if(isInputRange!T)
{
    ...
}

Static arrays are _not_ ranges and _cannot_ be ranges. At their must basic
level (the input range), ranges must implement empty, front, and popFront, and
static arrays _cannot_ implement popFront, because you cannot change their
length. The _only_ way that a static array can be passed to a range-based
function is if it's sliced so that you have a dynamic array (which _is_ a
range). And as templates take the _exact_ type, no templated function will
automatically slice a static array for you. The language _could_ be changed so
that IFTI treated static arrays as dynamic arrays and automatically sliced
them, but then you'd have problems creating templated functions that actually
wanted to take static arrays rather than dynamic ones.

You _could_ overload every range-based function with an overload specifically
for dynamic arrays (with the idea that the static array would be sliced when
it's passed to it as happens with non-templated functions which take dynamic
arrays), but that would be a royal pain. It would also significantly increase
the risk of using static arrays, because you'd end up returning ranges which
reference the static array from whatever range-based function you called, and
the fact that you're dealing with a static array could very quickly become
buried (easily resulting in returning a range to a static array which then no
longer exists, because it was a local variable). It's much better to require
that the programmer explicitly slice the static array, because then they know
that they're slicing it and then can know that they have to watch to make sure
that no reference to that static array escapes.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------


More information about the Digitalmars-d-bugs mailing list