Search code examples
d

Is there any way to assign multiple variable at once with Dlang?


With using Ruby, we can do this.

s = "split by space"
A,B,C = s.split(" ").map(&:to_i)

With using D-lang, it's compile error.

string s = "split by space";
int A,B,C = s.split(" ").map!(x => x.to!int);

Solution

  • Jonathan is mostly right, but there is in fact a way to split a tuple into its constituent parts, albeit more verbose than in Ruby, and without any handy type inference:

    import std.meta : AliasSeq;
    import std.typecons : tuple;
    
    auto foo() { return tuple(42, 29, "hello"); }
    
    unittest {
       int a, b;
       string c;
       AliasSeq!(a, b, c) = foo(); // Look ma, magic!
       assert(a == 42);
       assert(b == 29);
       assert(c == "hello");
    }
    

    While there's no built-in way to do this with ranges like your example, it's possible to implement in a library:

    import std.meta : AliasSeq, Repeat;
    import std.typecons : Tuple, tuple;
    import std.algorithm : map;
    import std.conv : to;
    import std.string : split;
    import std.range : isInputRange, ElementType;
    
    unittest {
       string s = "1 2 3";
       int A,B,C;
       AliasSeq!(A,B,C) = s.split(" ").map!(x => x.to!int).tuplify!3;
       assert(A == 1);
       assert(B == 2);
       assert(C == 3);
    }
    
    auto tuplify(size_t n, R)(R r) if (isInputRange!R) {
       Tuple!(Repeat!(n, ElementType!R)) result;
    
       static foreach (i; 0..n) {
          result[i] = r.front;
          r.popFront();
       }
       assert(r.empty);
    
       return result;
    }