Jump to page: 1 2
Thread overview
Another interesting hack: expand a static array into parameter arguments
Apr 02, 2014
Andrej Mitrovic
Apr 02, 2014
Andrej Mitrovic
Apr 02, 2014
Timon Gehr
Apr 02, 2014
Andrej Mitrovic
Apr 02, 2014
Andrej Mitrovic
Apr 02, 2014
Simen Kjærås
Apr 03, 2014
Andrej Mitrovic
Apr 03, 2014
Andrej Mitrovic
Apr 02, 2014
Artur Skawina
Apr 02, 2014
w0rp
Apr 03, 2014
Andrej Mitrovic
Apr 03, 2014
monarch_dodra
Apr 03, 2014
Artur Skawina
Apr 03, 2014
Andrej Mitrovic
Apr 03, 2014
Dicebot
Apr 03, 2014
Artur Skawina
Apr 02, 2014
bearophile
Apr 03, 2014
Andrej Mitrovic
Apr 03, 2014
bearophile
April 02, 2014
-----
import std.stdio;
import std.typetuple;

auto Delay(alias arg, size_t idx)() { return arg[idx]; }

template expand(alias args, size_t idx = 0)
{
    alias Args = typeof(args);

    static if (is(Args : C[N], C, size_t N))
    {
        static if (idx < (N - 1))
            alias expand = TypeTuple!(Delay!(args, idx),
                                      expand!(args, idx + 1));
        else
            alias expand = Delay!(args, N - 1);
    }
}

void foo(int a, int b, int c)
{
    writefln("a: %s, b: %s, c: %s", a, b, c);
}

void main()
{
    int[3] arr = [1, 2, 3];
    foo(expand!arr);
}
-----
April 02, 2014
On Wednesday, 2 April 2014 at 19:40:41 UTC, Andrej Mitrovic wrote:
> snip

Cleaned up version:

-----
import std.stdio;
import std.traits;
import std.typetuple;

auto Delay(alias arg, size_t idx)() { return arg[idx]; }

template expand(alias array, size_t idx = 0)
    if (isStaticArray!(typeof(array)))
{
    alias Array = typeof(array);

    static if (idx + 1 < Array.length)
        alias expand = TypeTuple!(Delay!(array, idx),
                                  expand!(array, idx + 1));
    else
        alias expand = Delay!(array, idx);
}

void print(int a) { writefln("1: %s", a); }
void print(int a, int b) { writefln("2: %s %s", a, b); }
void print(int a, int b, int c) { writefln("3: %s %s %s", a, b, c); }

void main()
{
    int[1] arr1 = [1];
    int[2] arr2 = [1, 2];
    int[3] arr3 = [1, 2, 3];

    print(expand!arr1);
    print(expand!arr2);
    print(expand!arr3);
}
-----
April 02, 2014
On 04/02/2014 09:46 PM, Andrej Mitrovic wrote:
> On Wednesday, 2 April 2014 at 19:40:41 UTC, Andrej Mitrovic wrote:
>> snip
>

Nice.

> Cleaned up version:
>...
> auto Delay(alias arg, size_t idx)() { return arg[idx]; }

I guess this would be more useful as a ref-returning @property function?
April 02, 2014
On 4/2/14, Timon Gehr <timon.gehr@gmx.ch> wrote:
> I guess this would be more useful as a ref-returning @property function?

Good point.
April 02, 2014
On 4/2/14, Andrej Mitrovic <andrej.mitrovich@gmail.com> wrote:
> On 4/2/14, Timon Gehr <timon.gehr@gmx.ch> wrote:
>> I guess this would be more useful as a ref-returning @property function?
>
> Good point.

It can even be done inside the template:

-----
template expand(alias array, size_t idx = 0)
    if (isStaticArray!(typeof(array)))
{
    static @property ref Delay(alias arg, size_t idx)() { return arg[idx]; }

    alias Array = typeof(array);

    static if (idx + 1 < Array.length)
        alias expand = TypeTuple!(Delay!(array, idx),
                                  expand!(array, idx + 1));
    else
        alias expand = Delay!(array, idx);
}
-----
April 02, 2014
On 2014-04-02 20:54, Andrej Mitrovic wrote:
> On 4/2/14, Andrej Mitrovic <andrej.mitrovich@gmail.com> wrote:
>> On 4/2/14, Timon Gehr <timon.gehr@gmx.ch> wrote:
>>> I guess this would be more useful as a ref-returning @property function?
>>
>> Good point.
>
> It can even be done inside the template:
>
> -----
> template expand(alias array, size_t idx = 0)
>      if (isStaticArray!(typeof(array)))
> {
>      static @property ref Delay(alias arg, size_t idx)() { return arg[idx]; }
>
>      alias Array = typeof(array);
>
>      static if (idx + 1 < Array.length)
>          alias expand = TypeTuple!(Delay!(array, idx),
>                                    expand!(array, idx + 1));
>      else
>          alias expand = Delay!(array, idx);
> }
> -----

In fact, it does not even need to have arg and idx explicitly passed, and the alias for Array is redundant:

template expand(alias array, size_t idx = 0)
    if (isStaticArray!(typeof(array)))
{
    @property ref Delay() {
        return array[idx];
    }
    static if (idx + 1 < array.length) {
        alias expand = TypeTuple!(Delay, expand!(array, idx + 1));
    } else {
        alias expand = Delay;
    }
}

--
  Simen
April 02, 2014
Andrej Mitrovic:

> void foo(int a, int b, int c)
> {
>     writefln("a: %s, b: %s, c: %s", a, b, c);
> }
>
> void main()
> {
>     int[3] arr = [1, 2, 3];
>     foo(expand!arr);
> }
> -----

In Python2 and Haskell it's a built-in feature, as it should be:

>>> def foo((x, y, z)): print x, y, z
...
>>> foo([1, 2, 3])
1 2 3
>>> def bar(x, y, z): print x, y, z
...
>>> a = [1, 2, 3]
>>> bar(*a)
1 2 3


Prelude> let foo [x, y, z] = show x ++ ", " ++ show y ++ ", " ++ show z
Prelude> let a = [1, 2, 3]
Prelude> foo a
"1, 2, 3"

Bye,
bearophile
April 02, 2014
On 04/02/14 21:46, Andrej Mitrovic wrote:
> auto Delay(alias arg, size_t idx)() { return arg[idx]; }
> 
> template expand(alias array, size_t idx = 0)
>     if (isStaticArray!(typeof(array)))
> {
>     alias Array = typeof(array);
> 
>     static if (idx + 1 < Array.length)
>         alias expand = TypeTuple!(Delay!(array, idx),
>                                   expand!(array, idx + 1));
>     else
>         alias expand = Delay!(array, idx);
> }


   template expand(alias A, alias M=Delay) {
      mixin(q{alias expand = TypeTuple!(}
             ~ iota(A.length).map!q{",M!(A,"[!a..$]~text(a)~")"}().join()
             ~ q{);});
   }

SCNR.

artur
April 02, 2014
On Wednesday, 2 April 2014 at 21:53:57 UTC, Artur Skawina wrote:
>    template expand(alias A, alias M=Delay) {
>       mixin(q{alias expand = TypeTuple!(}
>              ~ iota(A.length).map!q{",M!(A,"[!a..$]~text(a)~")"}().join()
>              ~ q{);});
>    }
>
> SCNR.
>
> artur

I kind of started this whole topic off from IRC.

...

What have I done!?
April 03, 2014
On 4/2/14, Artur Skawina <art.08.09@gmail.com> wrote:
>    template expand(alias A, alias M=Delay) {
>       mixin(q{alias expand = TypeTuple!(}
>              ~ iota(A.length).map!q{",M!(A,"[!a..$]~text(a)~")"}().join()
>              ~ q{);});
>    }

You can always use string mixins for these hacks. But they are terrible to debug, and likely slower to compile. I can barely make out what the above code does even though I deal with mixins and templates every day.
« First   ‹ Prev
1 2