December 17, 2014
On 17.12.14 13:30, Tobias Pankrath wrote:
> void append(T, Args...)(ref T[] data, Args args)
> {
>      static size_t estimateLength(Args args)
>      {
>          size_t result;
>          foreach(e; args)
>              static if(hasLength!(typeof(e)))
>                  result += e.length;
>              else
>                  result += 1;
>
>          return result;
>      }
>
>      auto app = appender!(T[])(data);
>      app.reserve(data.length + estimateLength(args));
>
>      foreach(e; args)
>          app.put(e);
>      data = app.data;
> }
>
> void main()
> {
>      import std.stdio;
>      int[] data;
>      append(data, 1, 2, only(1, 2, 3), iota(4, 9));
>      writeln(data);
> }
>
> ---
>
> Maybe appender.put should get an overload that does the same, though I
> didn't had the need for it yet.

It's for convenient one line: arr.append(e1, e2, ...);
I said "something like that" :)
December 18, 2014
On 12/17/14 6:15 AM, zeljkog wrote:
> On 15.12.14 01:00, "Nordlöw" wrote:
>> Isn't this algorithm already encoded somewhere in Phobos?
>
> void append(T, Args...)(ref T[] arr, auto ref Args args){
> {
>     static if (args.length == 1)
>        arr ~= args[0];     // inlined
>     else{
>        arr.length += args.length;
>        foreach(i, e; args)
>           arr[$ - args.length + i] = e;
>     }
> }
>
> I've just tested, this looks usable.
> Equal for 1 item, considerably (~40%) faster for 2, and much (100+%) faster for more.
> Also more convenient.

This makes sense. The cost of calling a function is much much higher than copying a single element.

> Maybe samthing like that should go to Fobos.

Definitely. I would love to see the improvement, however, of having arr ~= [a, b, c] do this automatically by the compiler.

I wonder how your code compares to this:

void append(T)(ref T[] arr, T[] args...)
{
   arr ~= args;
}

Which is how I would have approached it. Your solution is more general, but mine has the benefit of avoiding the double-initialization of the data.

-Steve
December 18, 2014
On Wednesday, 17 December 2014 at 12:30:37 UTC, Tobias Pankrath wrote:
>> void append(T, Args...)(ref T[] arr, auto ref Args args){
>> {
>>   static if (args.length == 1)
>>      arr ~= args[0];     // inlined
>>   else{
>>      arr.length += args.length;
>>      foreach(i, e; args)
>>         arr[$ - args.length + i] = e;
>>   }
>> }

Is it un-Phobos-like to make append return a reference to data like at

https://github.com/nordlow/justd/blob/master/algorithm_ex.d#L1605
December 18, 2014
On Thursday, 18 December 2014 at 15:12:39 UTC, Nordlöw wrote:
> On Wednesday, 17 December 2014 at 12:30:37 UTC, Tobias Pankrath wrote:
>>> void append(T, Args...)(ref T[] arr, auto ref Args args){
>>> {
>>>  static if (args.length == 1)
>>>     arr ~= args[0];     // inlined
>>>  else{
>>>     arr.length += args.length;
>>>     foreach(i, e; args)
>>>        arr[$ - args.length + i] = e;
>>>  }
>>> }
>
> Is it un-Phobos-like to make append return a reference to data like at
>
> https://github.com/nordlow/justd/blob/master/algorithm_ex.d#L1605

I don't now, returning it at least allows chaining, which is nice.

You shouldn't use my code verbatim though. For example, you should only use x.length, if x is of element type of data. Otherwise if you have e.g. an array of array you'd get totally wrong numbers.
December 18, 2014
On 18.12.14 14:50, Steven Schveighoffer wrote:
> I wonder how your code compares to this:
> 
> void append(T)(ref T[] arr, T[] args...)
> {
>     arr ~= args;
> }

This is ~20% slower for ints, but it difference  increases for bigger structs.
December 19, 2014
On Thursday, 18 December 2014 at 22:27:06 UTC, zeljkog wrote:
> On 18.12.14 14:50, Steven Schveighoffer wrote:
>> I wonder how your code compares to this:
>> 
>> void append(T)(ref T[] arr, T[] args...)
>> {
>>     arr ~= args;
>> }
>
> This is ~20% slower for ints, but it difference  increases for bigger structs.

What a big surprise. If you make an array of struct, each item of your array has the length of the struct. structs a values.
If you want to append a struct to an array just append a pointer to the struct:

----------
struct arg{uint a,r,g,h;};

arg * [] argh;
arg [] argv;

foreach(immutable i; 0..1000)
  argh ~= new arg;
----------

so in argh, each item is a size_t pointer. damn.
In argv, the delta between each item is (a.sizeof+r.sizeof+g.sizeof+h.sizeof)
In argh, the delta between each item is (arg *).sizeof

December 19, 2014
On 12/18/14 5:27 PM, zeljkog wrote:
> On 18.12.14 14:50, Steven Schveighoffer wrote:
>> I wonder how your code compares to this:
>>
>> void append(T)(ref T[] arr, T[] args...)
>> {
>>      arr ~= args;
>> }
>
> This is ~20% slower for ints, but it difference  increases for bigger structs.
>

This is surprising to me. I would expect especially ints to be faster. In reality, there is no difference between arr ~= args and arr.length += args.length, and then copying, it's just how you do the copying. Perhaps it's the call to memcpy in the runtime that is slower than looping.

Did you compile both tests with the same command line parameters?

-Steve
December 19, 2014
On 19.12.14 16:25, Steven Schveighoffer wrote:
> This is surprising to me. I would expect especially ints to be faster.
> In reality, there is no difference between arr ~= args and arr.length +=
> args.length, and then copying, it's just how you do the copying. Perhaps
> it's the call to memcpy in the runtime that is slower than looping.
>

I think it's compile time looping, it's unrolled.

> Did you compile both tests with the same command line parameters?

Yes.
December 19, 2014
On 12/19/14 10:42 AM, zeljkog wrote:
> On 19.12.14 16:25, Steven Schveighoffer wrote:
>> This is surprising to me. I would expect especially ints to be faster.
>> In reality, there is no difference between arr ~= args and arr.length +=
>> args.length, and then copying, it's just how you do the copying. Perhaps
>> it's the call to memcpy in the runtime that is slower than looping.
>>
>
> I think it's compile time looping, it's unrolled.

Ah, good point. Your solution is definitely preferable then, and I hope at some point the compiler can make that the result of appending an array literal.

-Steve
December 19, 2014
On Friday, 19 December 2014 at 15:25:46 UTC, Steven Schveighoffer wrote:
> On 12/18/14 5:27 PM, zeljkog wrote:
>> On 18.12.14 14:50, Steven Schveighoffer wrote:
>>> I wonder how your code compares to this:
>>>
>>> void append(T)(ref T[] arr, T[] args...)
>>> {
>>>     arr ~= args;
>>> }
>>
>> This is ~20% slower for ints, but it difference  increases for bigger structs.
>>
>
> This is surprising to me.
>
> -Steve

Ho ho ho, this year he has brought your surprise sooner than expected...