Thread overview
.tupleof for static array
Aug 10, 2021
Dennis
Aug 10, 2021
jfondren
Aug 10, 2021
Dennis
Aug 10, 2021
Paul Backus
Aug 10, 2021
Dennis
Aug 10, 2021
Paul Backus
August 10, 2021
struct Vec {
    float x, y, z;
}

void setPosition(float x, float y, float z) {

}

void main() {
    Vec posS = Vec(10, 20, 30);
    setPosition(posS.tupleof); // pass

    float[3] posA = [10, 20, 30];
    setPosition(posA.tupleof); // Error: no property `tupleof` for type `float[3]`
}

Does anyone know a library utility to make expanding a static array like this work?

August 10, 2021

On Tuesday, 10 August 2021 at 12:01:24 UTC, Dennis wrote:

>
struct Vec {
    float x, y, z;
}

void setPosition(float x, float y, float z) {

}

void main() {
    Vec posS = Vec(10, 20, 30);
    setPosition(posS.tupleof); // pass

    float[3] posA = [10, 20, 30];
    setPosition(posA.tupleof); // Error: no property `tupleof` for type `float[3]`
}

Does anyone know a library utility to make expanding a static array like this work?

I came up with

auto structOf(T, size_t N)(T[N] xs) {
    string defstruct(size_t n) {
        import std.conv : to;

        string m = "struct S { " ~ T.stringof;
        foreach (i; 1 .. n) {
            m ~= " _";
            m ~= i.to!string;
            m ~= ",";
        }
        m ~= " _n; }";
        return m;
    }

    mixin(defstruct(N));
    return cast(S) xs;
}

for structOf(posA).tupleof

And I don't see very many static-array-generic functions in Phobos.

August 10, 2021

Thanks! I was considering turning the static array into an AliasSeq directly, but casting it to a struct and doing tupleof on that is pretty smart.

On Tuesday, 10 August 2021 at 12:50:55 UTC, jfondren wrote:

>

And I don't see very many static-array-generic functions in Phobos.

Indeed, static arrays could use some more love in my opinion.

August 10, 2021

On Tuesday, 10 August 2021 at 12:01:24 UTC, Dennis wrote:

>
struct Vec {
    float x, y, z;
}

void setPosition(float x, float y, float z) {

}

void main() {
    Vec posS = Vec(10, 20, 30);
    setPosition(posS.tupleof); // pass

    float[3] posA = [10, 20, 30];
    setPosition(posA.tupleof); // Error: no property `tupleof` for type `float[3]`
}

Does anyone know a library utility to make expanding a static array like this work?

import std.traits: isStaticArray;

template Iota(size_t n)
{
    import std.meta: AliasSeq;

    static if (n == 0)
        alias Iota = AliasSeq!();
    else
        alias Iota = AliasSeq!(Iota!(n - 1), n - 1);
}

template tupleOf(alias array)
    if (isStaticArray!(typeof(array)))
{
    import std.meta: Map = staticMap;

    ref element(size_t i)()
    {
        return array[i];
    }

    alias tupleOf = Map!(element, Iota!(array.length));
}

Full example: https://run.dlang.io/is/COG7m4

Would definitely be nice to have this in the language, though.

August 10, 2021

Thanks for this solution as well.

On Tuesday, 10 August 2021 at 13:10:23 UTC, Paul Backus wrote:

>

Would definitely be nice to have this in the language, though.

Do you know more use cases for this?

August 10, 2021

On Tuesday, 10 August 2021 at 15:32:25 UTC, Dennis wrote:

>

Thanks for this solution as well.

On Tuesday, 10 August 2021 at 13:10:23 UTC, Paul Backus wrote:

>

Would definitely be nice to have this in the language, though.

Do you know more use cases for this?

I've written range pipelines like this:

someSourceRange
    .chunks(2)
    .map!(chunk => chunk.staticArray!2) // allows random access
    .each!(pair => doSomethingWith(pair[0], pair[1]));

Having to write pair[0] and pair[1] is a bit awkward, though. Normally I would use something like the following to bind each element to a separate parameter:

alias apply(alias fun) = args => fun(args.tupleof);

/* ... */
    .each!(apply!((first, second) => doSomethingWith(first, second)));

...but .tupleof doesn't work with static arrays, so that doesn't compile.