October 21, 2013
On Monday, 21 October 2013 at 19:37:47 UTC, Jonathan M Davis wrote:
> On Monday, October 21, 2013 21:16:00 qznc wrote:
>> On Monday, 21 October 2013 at 16:22:29 UTC, Krzysztof Ciebiera
>> 
>> wrote:
>> > I understand slices now and I don't find it consistent with "no
>> > shoot in the foot by default" statement.
>> 
>> I agree. The pitfalls are well understood, yet everybody seems to
>> love them. Ok, compared to C array they are an improvement due to
>> bounds checking. If the elements are const or immutable (string)
>> everything is fine, but write+append is basically
>> implementation-defined behavior.
>> 
>> Once there is a proper std.collections, I will probably adapt my
>> tutorial to recommend a safe alternative (ArrayList?).
>
> Just don't use slices when appending. It's only an issue when you're appending
> and relying on slices continuing to refer to the same array, and that's not
> going to work. Slices are primarily for reading, not writing. Using a
> container doesn't change that. It just makes it so that you can't even attempt
> to append to a slice, because the slice is a different type than that container
> and won't support appending.
>
> - Jonathan m Davis

What would be the issue/s with disallowing appending to slices? So you'd have to explicitly duplicate before you could append.
October 21, 2013
On Monday, October 21, 2013 22:14:08 ixid wrote:
> What would be the issue/s with disallowing appending to slices? So you'd have to explicitly duplicate before you could append.

All arrays are slices. There is no difference between the two. It's just that if you start appending to one, it will eventually no longer point to the same block of memory as any other arrays that pointed to the block of memory that it was pointing to. So, there's no way for the compiler to know whether you're trying to append to an array that was created by slicing another array as opposed to being directly allocated.

Also, disallowing appending to slices would be needlessly restrictive even if you could have that restriction. There's nothing wrong whatsoever with appending to a slice. It just means that you have to be aware that it may end up reallocating and not be a slice of the same memory anymore. So, if you want to avoid that, then don't append to the array. If you don't mind that it reallocates for what your code is doing, then it's not a problem. All it means is that you have to be aware that appending to an array may make it so that it will reallocate. Whether that's good or bad depends on what you're doing.

- Jonathan M Davis
October 22, 2013
On Monday, 21 October 2013 at 20:14:09 UTC, ixid wrote:
> On Monday, 21 October 2013 at 19:37:47 UTC, Jonathan M Davis wrote:
>> On Monday, October 21, 2013 21:16:00 qznc wrote:
>>> On Monday, 21 October 2013 at 16:22:29 UTC, Krzysztof Ciebiera
>>> 
>>> wrote:
>>> > I understand slices now and I don't find it consistent with "no
>>> > shoot in the foot by default" statement.
>>> 
>>> I agree. The pitfalls are well understood, yet everybody seems to
>>> love them. Ok, compared to C array they are an improvement due to
>>> bounds checking. If the elements are const or immutable (string)
>>> everything is fine, but write+append is basically
>>> implementation-defined behavior.
>>> 
>>> Once there is a proper std.collections, I will probably adapt my
>>> tutorial to recommend a safe alternative (ArrayList?).
>>
>> Just don't use slices when appending. It's only an issue when you're appending
>> and relying on slices continuing to refer to the same array, and that's not
>> going to work. Slices are primarily for reading, not writing. Using a
>> container doesn't change that. It just makes it so that you can't even attempt
>> to append to a slice, because the slice is a different type than that container
>> and won't support appending.
>
> What would be the issue/s with disallowing appending to slices? So you'd have to explicitly duplicate before you could append.

Appending itself is not the problem. Append + write is indeterministic.

 int[] a = [1,2,3];
 int[] b = a;
 a ~= [4,5]; // append
 a[0] = 42; // write
 assert (b[0] == 42) // indeterministic, implementation-specific

It depends on the capacity during the append. If a reallocation happened, then b[0]==1. Otherwise b[0]==42.

If you can forbid the write (e.g. immutable(char)[] aka string), you can append as much as you want. If you can disallow the append (convention, no type system support for this), you can write as much as you want.

For something like Javas ArrayList, the behavior would be a deterministic b[0]==42, but also a.length==b.length.
1 2
Next ›   Last »