October 18, 2013
Adam D. Ruppe:

>     arr.length = arr.length - 1; // arr.length-- won't compile due to silliness

This code now compiles, the bug was fixed:


void foo(ref int[] arr) {
    arr.length--;
}
void main() {}


Bye,
bearophile
October 18, 2013
On Friday, 18 October 2013 at 14:29:44 UTC, Dicebot wrote:
> On Friday, 18 October 2013 at 14:27:36 UTC, Adam D. Ruppe wrote:
>>    for(size_t idx = index; idx < arr.length - 1; idx++)
>>        arr[idx] = arr[idx + 1];
>
> You can do it via slice element-wise assignment:
>
> arr[index..$-1][] = arr[index+1..$][]

Ah, nvm, it will trigger an exception for overlapping source and dest.
October 18, 2013
On Friday, 18 October 2013 at 14:29:44 UTC, Dicebot wrote:
> You can do it via slice element-wise assignment:

nope, run the copy syntax and get this:

object.Error: overlapping array copy

(unless this was changed recently too)
October 18, 2013
Dicebot:

> You can do it via slice element-wise assignment:
>
> arr[index..$-1][] = arr[index+1..$][]

Overlapping slices error. You have to copy with Phobos...

Bye,
bearophile
October 18, 2013
On 10/17/13 10:45 PM, Jesse Phillips wrote:
> I believe this
> was the behavior of D1, is not true in D2 and must not be true for
> immutable arrays such as string.

Yes, there have been repeated discussions in this group about changing that behavior, it created pernicious long-distance dependencies (someone would pass a slice to someone else, and they'd start trampling into the caller's data. For a while it seemed there would be no reasonable solution, until we finally figured the whole capacity caching thing.

Andrei

October 19, 2013
On Friday, 18 October 2013 at 13:38:01 UTC, Vitali wrote:
> With this in mind I take back everything I said about slices and leave only a doubt that slices are performant.

By avoiding the concatenation operators and expansion through increasing the length property, slices can be used separately from the runtime's opaque dynamic array type. Slices can be backed by any memory by slicing a pointer or fixed-length array. Also, slices with compile-time initializers are backed either by TLS or global memory.

There is also one incidence in the language where such a non-runtime-backed slice appears implicitly:

---
void foo(int[] numbers...);

void main()
{
    foo([1, 2]); // Uses a GC-managed array for `numbers`
    foo(1, 2); // Uses a stack-allocated array for `numbers`
}
---
October 19, 2013
On Saturday, 19 October 2013 at 03:46:52 UTC, Jakob Ovrum wrote:
> By avoiding the concatenation operators and expansion through increasing the length property, slices can be used separately from the runtime's opaque dynamic array type. Slices can be backed by any memory by slicing a pointer or fixed-length array. Also, slices with compile-time initializers are backed either by TLS or global memory.

Also, string literals are backed by global memory (sometimes ROM).

> There is also one incidence in the language where such a non-runtime-backed slice appears implicitly:

To clarify: there is one incidence where a slice of *stack memory* is implicitly created.
January 15, 2014
On Thu, 17 Oct 2013 23:45:18 -0400, Ali Çehreli <acehreli@yahoo.com> wrote:

> On 10/17/2013 03:33 PM, Sean Kelly wrote:
>
>  > I'd be curious to see if this would ever relocate:
>  >
>  > int[] dArr = [10,11,12];
>  > const(int)[] dSlice = dArr[0..2];
>  > dSlice.length++;
>  >
>  > It shouldn't, since growing a const slice can never clobber the
>  > underlying array,
>
> However, according to spec, the appended elements must be 0. There is an optimization opportunity if the elements beyond dSlice's end were all zeros and if the type system guaranteed that they were immutable. Only then dSlice's relocation could be elided.

(catching up on D forums)

Ali is correct, the above code will always reallocate. Underneath, the array runtime has no specialized code to deal with const, only shared.

In reality, the dSlice.length++ line is equivalent to doing:

dSlice ~= int.init;

for all flavors of const.

-Steve
January 15, 2014
On Fri, 18 Oct 2013 01:45:30 -0400, Jesse Phillips <Jesse.K.Phillips+D@gmail.com> wrote:

> On Thursday, 17 October 2013 at 20:03:53 UTC, Vitali wrote:
>>   arrPtr1 = arr.ptr;
>>   arr.reserve(5);     // reserve capacity
>>   arrPtr2 = arr.ptr;
>>   assert(arrPtr1 != arrPtr2); // ok, this makes sense
>>   assert(arr.capacity==7); // ok, this makes not so
>>   // much sense, but it's bigger than 5,
>>   // I guess it's ok
>>
>>   // I reserved extra capacity. I got more
>>   // than I needed, but ok.
>
> It will reserve enough memory for the requested size, in doing so it will allocate on some hardware friendly boundary. (Others here have a better grasp on why and what that is).

The memory allocator works in powers of 2 bytes from 16 to PAGE size. A D array has runtime data to maintain inside the block, which is why the resulting array length is a power of 2 - 1.

For instance, 5 integers would only fit into a block of 32 bytes. You may expect a capacity of 8, and it would be true, except the runtime has to actually store the capacity somewhere, so it consumes some bytes to do that inside the block itself. So a block of 8 ints becomes a block of 7 ints. There is also the issue of needing a sentinel byte between blocks to prevent leaking into the next block. So the last element was wasted anyway before I added the capacity.

-Steve
1 2 3 4
Next ›   Last »