July 17, 2017
OK, here's an actual, compilable, runnable version:

	import std.algorithm : sum;
	import std.meta : allSatisfy, staticMap;
	import std.range : only;
	import std.traits : CommonType, isStaticArray;

	alias Elem(A : E[n], E, size_t n) = E;
	enum Length(A) = A.length;
	enum sumLengths(A...) = sum(only(0, staticMap!(Length, A)));

	CommonType!(staticMap!(Elem, A))[sumLengths!A] append(A...)(A arrays)
		if (allSatisfy!(isStaticArray, A))
	{
		typeof(return) result = void;
		foreach (i, a; arrays) {
			enum offset = sumLengths!(A[0 .. i]);
			result[offset .. offset + a.length] = a[];
		}
		return result;
	}

	@nogc unittest {
		int[2] a = [ 1, 2 ];
		int[3] b = [ 3, 4, 5 ];
		int[4] c = [ 6, 7, 8, 9 ];

		auto d = append(a, b, c);
		assert(is(typeof(d) == int[9]));
		assert(d == [ 1, 2, 3, 4, 5, 6, 7, 8, 9 ]);
	}


T

-- 
Be in denial for long enough, and one day you'll deny yourself of things you wish you hadn't.
July 17, 2017
On Monday, 17 July 2017 at 18:54:31 UTC, Stefan Koch wrote:
> So all you need to do make it so
> auto cat(T[]...)(T args)
> {
>     T[] result;
>     mixin(() {
>       string mix  = `result = `;
>       foreach(i;args.length)
>       {
>         mix ~= `args[` ~ itos(i) ~ `] ~`;
>       }
>       mix[$-1] = ';';
>       return mix;
>     }());
>
>     return result;
> }
>
> that should do it :)

Thanks, but I wan't a @nogc-variant, which was posted below.
July 17, 2017
On Monday, 17 July 2017 at 18:54:31 UTC, Stefan Koch wrote:
> we have special code in the compiler to optimize a ~ b ~ c.

Interesting, can you elaborate on what you mean with "optimize".

In that case, is there a reason why

    int x[2];
    int y[2];
    int z[x.length + y.length] = x ~ y;

isn't @nogc?
July 17, 2017
On Mon, Jul 17, 2017 at 08:11:03PM +0000, Nordlöw via Digitalmars-d-learn wrote: [...]
> Does this have a place in Phobos?

Never know till you try. :-D


> If so,
> 
> - under what name: append, concat or cat?

I'd vote for concat.


> - where: std.algorithm or std.array?

std.array, IMO, since it's specific to static arrays.


T

-- 
Without outlines, life would be pointless.
July 17, 2017
On Monday, 17 July 2017 at 19:11:26 UTC, H. S. Teoh wrote:
> Hmm, since we already have sumOfLengths available at compile-time, what about:
>
>  	T[sumOfLengths!StaticArrays] append(StaticArrays...)(StaticArrays arrays)
>  		if (allSatisfy!(isStaticArray, StaticArrays))
>  	{
>  		typeof(return) result = void;
>  		foreach (i, a; 0 .. arrays.length)
>  		{
> 			enum offset = sumOfLengths!(arrays[0 .. i]);
>  			result[offset .. offset + a.length] = a[];
>  		}
>  		return result;
>  	}
>
>
> T

Thanks, I'll try this!

Does this have a place in Phobos?

If so,

- under what name: append, concat or cat?
- where: std.algorithm or std.array?

July 17, 2017
On Monday, 17 July 2017 at 20:10:31 UTC, H. S. Teoh wrote:
> On Mon, Jul 17, 2017 at 08:11:03PM +0000, Nordlöw via Digitalmars-d-learn wrote: [...]
>> Does this have a place in Phobos?
>
> Never know till you try. :-D
>
>
>> If so,
>> 
>> - under what name: append, concat or cat?
>
> I'd vote for concat.
>
>
>> - where: std.algorithm or std.array?
>
> std.array, IMO, since it's specific to static arrays.
>
>
> T

Made some adjustments with working unittest and put it up on

https://github.com/nordlow/phobos-next/blob/master/src/algorithm_ex.d#L2467

I had to special-case foreach body for `i == 0` since `sumOfLengths` couldn't instantiate with empty tuple `()`.

Further, should `concat` support `CommonType`? That is, should

    int[2] x = [1, 2];
    const double[2] y = [3, 4];
    auto z = concat(x, y);
    static assert(is(typeof(z) == double[4]));

be allowed?
July 17, 2017
On Mon, Jul 17, 2017 at 08:28:12PM +0000, Nordlöw via Digitalmars-d-learn wrote: [...]
> I had to special-case foreach body for `i == 0` since `sumOfLengths` couldn't instantiate with empty tuple `()`.
> 
> Further, should `concat` support `CommonType`? That is, should
> 
>     int[2] x = [1, 2];
>     const double[2] y = [3, 4];
>     auto z = concat(x, y);
>     static assert(is(typeof(z) == double[4]));
> 
> be allowed?

See the working implementation in my latest post on this thread.  That version supports CommonType, and works correctly with empty tuples as well.


T

-- 
Trying to define yourself is like trying to bite your own teeth. -- Alan Watts
July 17, 2017
On Monday, 17 July 2017 at 20:53:36 UTC, H. S. Teoh wrote:
> See the working implementation in my latest post on this thread.  That version supports CommonType, and works correctly with empty tuples as well.
>
>
> T

Thanks.
July 17, 2017
On Monday, 17 July 2017 at 20:01:41 UTC, H. S. Teoh wrote:
> OK, here's an actual, compilable, runnable version:
>
> 	import std.algorithm : sum;
> 	import std.meta : allSatisfy, staticMap;
> 	import std.range : only;
> 	import std.traits : CommonType, isStaticArray;
>
> 	alias Elem(A : E[n], E, size_t n) = E;
> 	enum Length(A) = A.length;
> 	enum sumLengths(A...) = sum(only(0, staticMap!(Length, A)));
>
> 	CommonType!(staticMap!(Elem, A))[sumLengths!A] append(A...)(A arrays)
> 		if (allSatisfy!(isStaticArray, A))
> 	{
> 		typeof(return) result = void;
> 		foreach (i, a; arrays) {
> 			enum offset = sumLengths!(A[0 .. i]);
> 			result[offset .. offset + a.length] = a[];

This slice assignment doesn't support conversion between different element-types, for instance from `int[]` to `double[]`.

But I'm not convinced that we should allow `CommonType` when operator ~ doesn't.
July 17, 2017
On Mon, Jul 17, 2017 at 10:32:14PM +0000, Nordlöw via Digitalmars-d-learn wrote:
> On Monday, 17 July 2017 at 20:01:41 UTC, H. S. Teoh wrote:
[...]
> > 			result[offset .. offset + a.length] = a[];
> 
> This slice assignment doesn't support conversion between different element-types, for instance from `int[]` to `double[]`.
> 
> But I'm not convinced that we should allow `CommonType` when operator ~ doesn't.

True.  Maybe we should just leave out the `CommonType` thing for now. Not sure how to express that all element types should be equal in the sig constraints, though.

(It shouldn't be overly hard to support `CommonType`; just replace the slice assignment with a manual loop. But yeah, probably not worth the effort.)


T

-- 
Do not reason with the unreasonable; you lose by definition.