通过使用 Ruby,我们可以做到这一点。
s = "split by space"
A,B,C = s.split(" ").map(&:to_i)
Run Code Online (Sandbox Code Playgroud)
使用 D-lang,它是编译错误。
string s = "split by space";
int A,B,C = s.split(" ").map!(x => x.to!int);
Run Code Online (Sandbox Code Playgroud)
不,没有办法做到这一点。一直在谈论可能会向该语言添加元组支持,以便您可以像
int a;
int b;
string c;
(a, b, c) = foo();
Run Code Online (Sandbox Code Playgroud)
也许有一天这会发生,但现在不可能。最接近的是使用像std.typecons.Tuple / tuple这样的东西,这样你就可以做类似的事情
Tuple!(int, int, string) foo() { return tuple(42, 29, "hello"); }
Tuple!(int, int, string) result = foo();
Run Code Online (Sandbox Code Playgroud)
或者更有可能
auto foo() { return tuple(42, 29, "hello"); }
auto result = foo();
Run Code Online (Sandbox Code Playgroud)
但Tuple最终只是一个结构,你不能在另一端神奇地将它分开。您必须通过诸如result[0]or 之类的索引访问其成员result[1],或者如果您Tuple使用名称进行声明- 例如Tuple!(int, "x", int, "y", string, "str")- 那么您可以通过名称访问成员 - 例如result.x。因此,Tuple/tuple允许您返回多个值而无需为此显式声明结构类型,但它仍在为此创建结构类型,虽然它允许您轻松打包要返回的值,但它不允许您自动解包他们在另一端。这将需要某种我们没有的编译器支持。
然而,即使我们在语言中有更好的元组支持,比如
(a, b, c) = foo();
Run Code Online (Sandbox Code Playgroud)
工作,我怀疑你正在尝试做的事情会起作用,因为map专门返回一个范围。所以,它是一个带有成员函数的对象,而不是任何类型的要拆分的元组。它恰好代表了可以使用正确的函数调用集提取的值列表。并且它具有的值的数量在编译时是未知的,因此即使您假设编译器对范围原语的理解足以为您从中获取列表,它也不能在编译时保证有足够的值放入您尝试分配的变量中,更不用说有那么多的值了。所以,虽然做这样的事情并非不可能(例如,如果它抛出一个Error在编译时,如果范围内没有足够的值),如果实现了,我会感到惊讶。D 是一种静态类型语言,这将有效地使其一部分动态化,因此它在语言中将非常不合时宜。Ruby 是一种动态语言,所以它是一个非常不同的野兽。
无论如何,元组的任何改进都将是对语言的改进,并且必须通过DIP 流程并获得批准,而这样的事情还没有发生。
小智 5
乔纳森大部分是对的,但实际上有一种方法可以将 atuple拆分为其组成部分,尽管比 Ruby 更冗长,并且没有任何方便的类型推断:
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");
}
Run Code Online (Sandbox Code Playgroud)
虽然没有像您的示例那样的内置方法来执行此操作,但可以在库中实现:
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;
}
Run Code Online (Sandbox Code Playgroud)