Tuple Unpacking

Hi, I frequently want to unpack a tuple into a "list" of values, for example when calling a function or when constructing an enum variant:

let tuple = ("abc", 3, (1, 2));

fn myfn(s: &str, a: usize, bc: (usize, usize)) { ... }

enum MyEnum<'a> {
    Args(&'a str, usize, (usize, usize)),
    NoArgs,
}

myfn(tuple.clone().unpack());

let args = MyEnum::Args(tuple.unpack());

Maybe with a better syntax of some kind, maybe tuple.. or *tuple.

The current syntax would be (ignoring cloning):

let (s, a, bc) = tuple;
myfn(s, a, bc);
let args = MyEnum::Args(s, a, bc);

What do you think about this, may this eventually be added to the language?

The obvious question to be asked first here: If you have a situation where you tend to pack together some (&'a str, usize, (usize, usize)) why not define a struct?

#[derive(Copy, Clone)]
struct Foo<'a>(&'a str, usize, (usize, usize));

let tuple = Foo("abc", 3, (1, 2));

fn myfn(foo: Foo) {}

enum MyEnum<'a> {
    Args(Foo<'a>),
    NoArgs,
}

myfn(tuple);

let args = MyEnum::Args(tuple);
2 Likes

legitimate question, but for small tuples, usually (a, b), a struct for every case is not really efficient.

Another big question:

What is tuple.unpack() returning, and what is MyEnum::Args accepting. If these are functions, they need type signatures, and if they are not functions, they sure look confusingly like they are.

Fun fact, on nightly with fn_traits you can currently do

#![feature(fn_traits)]

let tuple = ("abc", 3, (1, 2));

fn myfn(s: &str, a: usize, bc: (usize, usize)) {}

enum MyEnum<'a> {
    Args(&'a str, usize, (usize, usize)),
    NoArgs,
}

myfn.call(tuple);

let args = MyEnum::Args.call(tuple);

(playground)

7 Likes

That is exactly what is missing. Some kind of argument list type. Basically a type for lists of values with different types. So basically a type for tuples without the brackets.

Another answer could be, enum variants and functions can just accept tuples with their respective arguments, but this may get confusing.

I read about that, but this still leaves the enum case open.

how exactly?

oh wait, I missed MyEnum::Args.call(tuple)..

ah okay that does solve this problem. :slightly_smiling_face:

Furthermore, you can implement your own Fn-like trait in stable and use it (for an arbitrary but limited maximum number of arguments).

Rust Playground

Edit: Fixed the playground link.

1 Like

Variadic generics will solve this, and they have a Draft RFC: Draft RFC: variadic generics · Issue #376 · rust-lang/rfcs (github.com).

1 Like

This is great to see! Thanks for referencing this

Some previous conversations:

2 Likes