how to assign multiple variables at once by unpacking array?

Jonathan M Davis newsgroup.d at jmdavisprog.com
Sun Oct 8 06:02:14 UTC 2023


On Saturday, October 7, 2023 1:31:45 AM MDT mw via Digitalmars-d-learn wrote:
> https://stackoverflow.com/questions/47046850/is-there-any-way-to-assign-mult
> iple-variable-at-once-with-dlang
>
> How to do this Python code in D:
>
> ```
>
> >>> s = "1 2 3"
> >>> A,B,C = map(int, s.split(" "))
> >>> A,B,C
>
> (1, 2, 3)
>
> ```
>
> Is there a better way (since 2017)?

This is the sort of feature that you're much more likely to see in a
dynamically typed language than a statically typed one, and you will almost
certainly never see it in D.

The problem is that the compiler needs to be able to verify that the types
match, and when the return type of a function is a dynamic array such as
int[], it has no way of knowing how many elements the array has and
therefore can't verify at compile time that the assignment will work. At
best, it could add a runtime check to verify that the number of elements
match, but that's not the sort of thing that you typically do with a
statically typed language.

This is in stark contrast to a dynamically typed language where such things
are often done, because everything is already being checked at runtime
anyway, and checking whether the number of elements match then isn't really
any different from checking that the actual types of the variables match
what you're trying to do with them. But statically typed languages expect to
be able to do all of those kinds of checks at compile time, which means that
they're typically not going to do something like convert an array of
arbitrary length to a set of variables like that.

Now, what D might gain the ability to do at some point is to return
language-defined tuples, meaning that you'd be able to do something like

(int, string, float) foo(string bar, int baz)
{
    ...
    return (i * 2, "hello", 2.7 * x);
}

and

(a, b, c) = foo("whatever", 42);

This would work with a statically typed language, because the types are all
known at compile time.

However, while there are some benefits to being able to do this, the
response by many programmers from statically typed languages is that it's
cleaner to create a struct for this sort of thing, since then the values are
contained together, and they have names associated with them (since they'll
be member variables of the struct). So, while some programmers definitely
want tuple types to be built into D, a number of others don't like the idea.
As such, it's an open question whether we'll ever have such tuples in D.

What we do currently have is Tuple and tuple in std.typecons. Tuple allows
you to create a struct with a given set of fields without explicitly
declaring it. e.g.

alias Foo = Tuple!(string, "name", int, "x", int, "y");
foo = Foo("Bob", 12, 22);
assert(foo.name == "Bob");
assert(foo.x == 12);
assert(foo.y == 22);
assert(foo[0] == "Bob");
assert(foo[1] == 12);
assert(foo[2] == 22);

and tuple allows you to create such a struct (without the field names)
simply by calling a function. e.g.

auto foo = tuple("Bob", 12, 22);
assert(foo[0] == "Bob");
assert(foo[1] == 12);
assert(foo[2] == 22);

So, it becomes possible to create a new struct type to return from a
function simply by calling tuple. e.g.

auto doStuff(string str, float f)
{
    ...
    return tuple(x, str[i .. $]);
}

And thanks to some magic in Tuple, you even get unpacking of a sort by using
AliasSeq. E.G.

AliasSeq!(a, b) = doStuff(bar, 2.7);

So, for many programmers, Tuple and tuple from std.typecons are good enough,
and whether we ever get tuples added to the language will largely depend on
whether anyone can come up with a proposal for them that convinces Walter
and Atila that they're worth adding.

Either way, the unpacking of dynamic arrays likely stands no chance
whatsoever of ever being added, because it would require runtime checks to
determine whether the unpacking was valid.

- Jonathan M Davis





More information about the Digitalmars-d-learn mailing list