Thread overview
Unpacking Slices
Jun 14, 2021
Justin Choi
Jun 14, 2021
Ali Çehreli
Jun 14, 2021
Vladimir Panteleev
Jun 15, 2021
jfondren
June 14, 2021

Is there any shortcut for unpacking slices like I'd want to do in a scenario like this?
info = readln.strip.split;
string a = info[0], b = info[1], c = info[2];

June 14, 2021
On 6/14/21 11:08 AM, Justin Choi wrote:
> Is there any shortcut for unpacking slices like I'd want to do in a scenario like this?
> `info = readln.strip.split;`
> `string a = info[0], b = info[1], c = info[2];`

D does not have automatic unpacking. Here is a quick, dirty, and fun experiment:

struct Unpack(Args...) {
  static string typeName(size_t n)() {
    return Args[n].stringof;
  }

  static char varName(size_t n) {
    return cast(char)('a' + n);
  }

  // Variable declarations
  static foreach (n; 0 .. Args.length) {
    mixin (typeName!n ~ ' ' ~ varName(n) ~ ';');
  }

  // Get by variable number
  auto get(size_t n)() {
    mixin ("return " ~ varName(n) ~ ';');
  }

  // Set by variable number
  auto set(size_t n, T)(T value) {
    mixin (varName(n) ~ " = value;");
  }
}

template unpack(Args...) {
  auto unpack(R)(R range) {
    auto result = Unpack!(Args)();
    static foreach (n; 0 .. Args.length) {
      import std.range : front, popFront;
      result.set!n(range.front);
      range.popFront();
    }
    return result;
  }
}

import std.stdio;
import std.string;

void main() {
  auto info = readln.strip.split;
  auto u = info.unpack!(string, string, string);

  // Variables are accessed by name as a, b, etc. or by number:
  assert(u.a == u.get!0);
  assert(u.b == u.get!1);
  assert(u.c == u.get!2);
}


When all variable types are the same, the usage can be improved to allow e.g.

  info.unpack!(3, string)

That's not implemented yet. :)

Ali
June 14, 2021

On Monday, 14 June 2021 at 18:08:27 UTC, Justin Choi wrote:

>

Is there any shortcut for unpacking slices like I'd want to do in a scenario like this?
info = readln.strip.split;
string a = info[0], b = info[1], c = info[2];

I tried to implement PHP's "list" language construct here, which does something similar:
https://github.com/cybershadow/ae/blob/next/utils/array.d#L763

For your example, it would look like:

string a, b, c;
list(a, b, c) = readln.strip.split;
June 15, 2021

On Monday, 14 June 2021 at 18:08:27 UTC, Justin Choi wrote:

>

Is there any shortcut for unpacking slices like I'd want to do in a scenario like this?
info = readln.strip.split;
string a = info[0], b = info[1], c = info[2];

This doesn't leave you with multiple local variables, but it leaves
you with names instead of numbers for the members of the slice:

import std.stdio, std.typecons, std.algorithm, std.array, std.conv, std.range;

auto tuple(string rawnames, T)(T[] vals) {
    const names = rawnames.splitter(' ').array;
    assert(names.length == vals.length, "wrong # params to tuple()");
    mixin("auto ret = Tuple!("
            ~ names.map!(n => T.stringof ~ `, "` ~ n ~ `"`).joiner(", ").array
            ~ ")("
            ~ names.length.iota.map!(i => "vals[" ~ i.to!string ~ "]").joiner(", ").array
            ~ ");");
    return ret;
}

void main() {
    int[] x = [1,2,3];
    auto tup = tuple!"a b c"(x);
    writeln(tup.b);
}