Thread overview
Destructured Tuple Assignment
May 15, 2015
Per Nordlöw
May 15, 2015
Per Nordlöw
May 15, 2015
Per Nordlöw
May 15, 2015
Per Nordlöw
May 15, 2015
John Colvin
May 15, 2015
Artur Skawina
May 15, 2015
Per Nordlöw
May 15, 2015
Per Nordlöw
May 15, 2015
Per Nordlöw
May 15, 2015
I recall having seen an example of using some D magic (via mixin perhaps?) to realize tuple destructuring in assignments like

    magic(first, _, second) = expression.findSplit(separator);

somewhere. But I can't seem to find it right now.

References anyone?

BTW :I'm aware of Kenjis PR, which I am very much longing for ;)
May 15, 2015
On Friday, 15 May 2015 at 10:23:24 UTC, Per Nordlöw wrote:
> I recall having seen an example of using some D magic (via mixin perhaps?) to realize tuple destructuring in assignments like
>
>     magic(first, _, second) = expression.findSplit(separator);

I found it:

http://forum.dlang.org/thread/ubrngkdmyduepmfkhefp@forum.dlang.org?page=1

I'm however still as frustrated because instead of having to specify tuple indexes explicitly as

     const result = expression.findSplit(separator);
     const first = result[0];
     const second = result[2];

I instead have to write types explicitly (no type-inference)

     string first, _, second; // non-generic unstable type guess
     tie(first, _, second) = expression.findSplit(separator);

or just as bad

     typeof(expression.findSplit(separator)[0]) first, _, second;
     tie(first, _, second) = expression.findSplit(separator);

Can this be solved with a mixin somehow?
May 15, 2015
On Friday, 15 May 2015 at 10:23:24 UTC, Per Nordlöw wrote:
> I recall having seen an example of using some D magic (via mixin perhaps?) to realize tuple destructuring in assignments like
>
>     magic(first, _, second) = expression.findSplit(separator);
>
> somewhere. But I can't seem to find it right now.
>
> References anyone?
>
> BTW :I'm aware of Kenjis PR, which I am very much longing for ;)

Well there's always this, which is a bit ugly:

typeof(expression) first, _, second;
TypeTuple!(first, _, second) = expression.findSplit(separator);

But of course the holy grail is being able to declare variables inline.
May 15, 2015
On Friday, 15 May 2015 at 10:46:32 UTC, Per Nordlöw wrote:
> Can this be solved with a mixin somehow?

To clarify, I want to be able to write

    let(first, _, second) = expression.findSplit(separator);

without having to first declare `first`, `_` and `second`.

I'm guessing the closest thing we can get in current D version is something like

    let(q{first, _, second},
        expression.findSplit(separator));

right?

Which might be good enough for now.
May 15, 2015
On Friday, 15 May 2015 at 11:04:24 UTC, Per Nordlöw wrote:
> I'm guessing the closest thing we can get in current D version is something like
>
>     let(q{first, _, second},
>         expression.findSplit(separator));
>
> right?

Correction: I believe it must look like

     let!q{first, _, second}(expression.findSplit(separator));

or

     let!`first, _, second`(expression.findSplit(separator));


Is it possible to define a let that does what I want here?

If so, could someone, pleeeze, help me write out a stub for this?

I'm guessing something along the lines of

mixin template let(string vars, Ts...)
{
    import std.range: splitter;

    // declare variables in current scope. TODO do we need a mixin here?
    foreach (i, var; vars.splitter(`, `))
    {
        mixin(Ts[i] ~ ` ` ~ var);
    }

    auto let(Tuple!Ts xs)
    {
        foreach (i, var; vars.splitter(`, `))
        {
            mixin(Ts[i] ~ ` = ` ~ xs[i]);
        }
    }
}

unittest
{
    let!q{first, _, second}(tuple(`first`, `_`, `second`));
}

but this fails in many ways.

Could someone, please help out here?
May 15, 2015
   import std.algorithm;

   template magicassign(A...) {
      void magicassign(B)(B b) @property {
         foreach(I, ref a; A)
            static if (!is(typeof(A[I]):typeof(null)))
               a = b[I];
      }
   }

   template let(string D) {
      mixin({
         enum sdsl = D.findSplit("=");
         mixin(`struct S { int `~sdsl[0]~`; }`);
         string code = `auto v = ` ~ sdsl[2] ~ `;`;
         foreach (I, _; typeof(S.tupleof))
            code ~= `auto ` ~ S.tupleof[I].stringof ~ ` = v[`~I.stringof~`]; `;
         return code;
      }());
   }

   void main(string[] args) {
      import std.stdio;

      string a, b;
      magicassign!(a, null, b) = args[1].findSplit("-");
      writeln(a);
      writeln(b);

      mixin let!q{ c, _, d = args[1].findSplit("-") };
      writeln(c);
      writeln(d);
   }

artur
May 15, 2015
On Friday, 15 May 2015 at 12:22:55 UTC, Artur Skawina wrote:
>    import std.algorithm;
>
>    template let(string D) {
>       mixin({
>          enum sdsl = D.findSplit("=");
>          mixin(`struct S { int `~sdsl[0]~`; }`);
>          string code = `auto v = ` ~ sdsl[2] ~ `;`;
>          foreach (I, _; typeof(S.tupleof))
>             code ~= `auto ` ~ S.tupleof[I].stringof ~ ` = v[`~I.stringof~`]; `;
>          return code;
>       }());
>    }

Thanks!
May 15, 2015
On Friday, 15 May 2015 at 12:22:55 UTC, Artur Skawina wrote:
>    template let(string D) {
>       mixin({
>          enum sdsl = D.findSplit("=");
>          mixin(`struct S { int `~sdsl[0]~`; }`);
>          string code = `auto v = ` ~ sdsl[2] ~ `;`;
>          foreach (I, _; typeof(S.tupleof))
>             code ~= `auto ` ~ S.tupleof[I].stringof ~ ` = v[`~I.stringof~`]; `;
>          return code;
>       }());
>    }

I added support for auto, const and immutable declarations at

https://github.com/nordlow/justd/blob/master/ties.d#L96

which allows usage as

    mixin let!q{ auto i, d, s, c = tuple(42, 3.14, `pi`, 'x') };
    mixin let!q{ const i, d, s, c = tuple(42, 3.14, `pi`, 'x') };
    mixin let!q{ immutable i, d, s, c = tuple(42, 3.14, `pi`, 'x') };

:)

See unittests for details
May 15, 2015
On Friday, 15 May 2015 at 13:40:01 UTC, Per Nordlöw wrote:
> I added support for auto, const and immutable declarations at
>
> https://github.com/nordlow/justd/blob/master/ties.d#L96

And support for ignoring `_` as a variable as:

    import std.algorithm.searching: findSplit;
    mixin let!q{ c, _, d = `11-12`.findSplit(`-`) };
    static assert(__traits(compiles, c == c));
    static assert(!__traits(compiles, _ == _)); // assert that it was ignored