Thinking about the difference between fixed and 'dynamic' arrays.

Basile B. b2.temp at gmx.com
Wed Nov 30 03:04:47 UTC 2022


On Tuesday, 29 November 2022 at 18:59:46 UTC, DLearner wrote:
> To me, it appears that there are really two (_entirely 
> separate_) concepts:
>
> A. Supporting the useful concept of variable length (but 
> otherwise entirely conventional) arrays;
> B. Supporting a language feature that acts as a window to an 
> array, through which that array can be manipulated.
>
> And currently these two concepts are combined.
>
> Suggestion: it would be clearer if the two concepts were 
> separated:
> 1. Convert 'int[] VarArr;' so it produces a straightforward 
> _value-type_ variable array, called 'VarArr';
> 2. Implement a new concept 'int slice Window;' to produce an 
> object of type 'int slice', called 'Window'.
>    'Window' is a 'slice' into an int array, not an array itself 
> or even a variable.
>
> Opinions?

I have implemented that in 
[styx](https://gitlab.com/styx-lang/styx).

1. You have the type for dynamic arrays, called TypeRcArray, 
syntax is  `Type[+]`
2. You have the type for slices (what you describe as a window), 
syntax is `Type[]`
but it is mostly obtained using expressions, e.g `mySlice = 
myRcArray[lo .. hi]` or
`myStaticArray[lo .. hi]` or `myPointer[lo .. hi]`.

This sounded like a good idea but it [has appeared very 
quickly](https://styx-lang.gitlab.io/styx/type.html#noteonlifetime) that slices are not so useful, especially when management is based on reference counting because then slices requires a form of management too. Here is why:

Main caracteristics of a slice are

- they cannot modify the identity of their sources. The identity 
of the source is what makes the integrity of a dynamic array, 
what makes their references countable. So it is the content 
pointer and the length. In consequence you cannot change the 
length of the source, you can only reduce the view. You can 
change the elements in the view.
- the length and the pointer are cached as a value on the stack 
while for a dynamic array this is stored before that data, on the 
heap.

Problems start happening when you escape a slice

```d
struct S
{
     var s32[] memberSlice;
}

function f(var S s): auto
{
     var s32[+] a = (new s32[+])(2);

     // problem 1 : `s` lifetime > `a` lifetime
     s = (a[]).tupleof;  // note: tuples are used in pace of 
struct literals

     // problem 2
     return a[1 .. $]; // a is automatically decref'd on return
                       // so the caller pulls a dead heap block.
}
```

Essentially slices are only useful to be consumed locally, 
typically

```d
while mySlice.length do
{
    slice = slice[1..$];
}
```

And that's it. So at first glance slices are some cool, 
simplified, functionally stripped down arrays but they introduce 
new problems, at least when management of dynamic arrays is based 
on reference counting. Those new problems can only be solved 
using lifetime analysis (so a compile-time check... still better 
than runtime ref counting however).


More information about the Digitalmars-d-learn mailing list