rfcs icon indicating copy to clipboard operation
rfcs copied to clipboard

Support flattening of tuples

Open Nokel81 opened this issue 6 years ago • 15 comments

I believe that there should be some way of flattening a tuple. The most common reason is probably from a macro or within one that calls a function that returns a tuple but the result of the macro is a flattened tuple.

Example:

(5, (10, "Hello World")) -> (5, 10, "Hello World")

This is currently not possible I believe

Nokel81 avatar Sep 04 '17 03:09 Nokel81

It would be generally nice to have more support for structural transformations. Variadic generics are going to help for sure. I think that once the language itself is powerful enough, these kinds of things can be done in 3rd party libs. Check Frunk's HList for inspiration.

golddranks avatar Sep 04 '17 03:09 golddranks

Yes I know of HList but native rust has tuple destruction

let (x, y, z) = (5, 10, "Hello World");

However, something like HList cannot support that. I am also not talking about indexing into a tuple.

Nokel81 avatar Sep 04 '17 03:09 Nokel81

What kind of situations would you use flattening tuples? I have not used nested tuples yet, but if I did, I would consider refactoring (nested tuples may be confusing)

jaroslaw-weber avatar Sep 07 '17 08:09 jaroslaw-weber

This would be mostly useful in the creation of macros. Say that you have a function that returns a tuple. And you want to create a macro that accepts multiple versions of the input but still outputs in a flat tuple.

This is desirable because of tuple destructoring.

Nokel81 avatar Sep 07 '17 12:09 Nokel81

It’s easy to solve with a type operator, but with (,), I’m not sure…

hadronized avatar Oct 18 '17 08:10 hadronized

I implemented this with specialization and auto trait.

See https://docs.rs/flatten/*/flatten/

How deeply nested it is doesn't matter and empty unit tuple () is removed. (this is same as python)

(1, (2, 3), (4, ((5,),), ), 6).flatten() == (1, 2, 3, 4, 5, 6)

Edit: more description

kdy1 avatar Dec 26 '17 12:12 kdy1

@kdy1 Perhaps this can be merged into frunk eventually? Might be good to have a larger crate with these sorts of facilities.

Centril avatar Dec 26 '17 12:12 Centril

@Centril frunk seems like a library for stable rust. If using cargo feature is ok, I will be happy to merge it into frunk.

kdy1 avatar Dec 26 '17 12:12 kdy1

Perhaps if we choose to pursue a dedicated syntax, this could work:

let a = 5;
let b = (10, "Hello World");
assert_eq!((a, ..b), (5, 10, "Hello World"));

bluebear94 avatar Jul 21 '20 20:07 bluebear94

..x already means RangeTo { end: x }. Try another symbol :wink:

kennytm avatar Jul 22 '20 08:07 kennytm

I second @Nokel81 request. This would also be very useful for working with Options and zip chains

let a_opt = Some(1)
let b_opt = Some(2)
let c_opt = Some(3)

if let ((a, b), c) = a_opt.zip(b_opt).zip(c_opt)
{
    some_fn(a, b, c);
}  

goldenHairDafo avatar Sep 09 '21 08:09 goldenHairDafo

I'm also in need of this feature in this kind of context:

  foo0
    .and(foo1)
    .and(foo2)
    // ... etc

where each and merge result, this result in (((a, b), c), d) not very user friendly. Thus it's not blocking at all my project.

Stargateur avatar Dec 06 '21 16:12 Stargateur

Well ... the dedicated syntax, how about this:

let a = 5;
let b = (10, "Hello World");
assert_eq!((a, ...b), (5, 10, "Hello World"));

I mean ...x; or, ....x ... 🤔 (maybe not a good idea ...)

yhm-amber avatar Mar 05 '24 10:03 yhm-amber

It could be useful in case if you have a frunk's hlist of a single type, then convert it to nested tuple, flatten tuple and then to [T; _].

Ddystopia avatar Apr 03 '24 19:04 Ddystopia

Unpopular and probably very bad syntax suggestion: jq can flatten lists into iterators using []

[1, 2, 3] |
[0, .[]] # produces [0, 1, 2, 3]

EIther way, I think the exact syntax is not really a concern here. We could start with less fancy syntax using whatever verbose primitives we could offer (just like try!(x) before x?), either using macros or magical traits or whatever and just progress on a concise syntax later.

SOF3 avatar Apr 19 '24 07:04 SOF3