How can you get the number of elements in a tuple?

How can you get the number of elements in a tuple? I want something like this:

let tup = (500, 400, 200);
let size = tup.len();    // it doesn't exist

Tuples are more like anonomous structs than arrays, so asking for it's length doesn't make much sense.

1 Like

You can't. A tuple is essentially a short hand for making a struct. This means it can contain a variety of different types but the downside is now iterators or lengths.

In your case, wouldn't an array be better? Assuming those numbers are of the same type.

1 Like

Here is "one" way:

fn get_num<T: Debug + Sized>(tuple: &T) -> usize {
    let s = format!("{:#?}", tuple);
    match s.contains("\","){
        true => {
            let parts = s.matches("\",").collect::<Vec<&str>>();
            parts.len()
        },
        _ => 1
    }
}
let my_tuple = ("hello", "world");
println!("Number of tuple elements: {}", get_num(&my_tuple));
2 Likes

If the above resolution is to be called many times, then you should really setup your program such that you have an array instead of a tuple because "get_num" is NOT performance-savvy. It runs in O(n) time. This said, don't use it if performance really counts.

I mean, to do it properly would be to create a generic trait for each length of tuple up to 12 so it ends up being a compile time value.

E.g.:

trait TupleLen {
    fn len(&self) -> usize;
}

impl<T1> TupleLen for (T1,) {
    fn len(&self) -> usize { 1 }
}
impl<T1,T2> TupleLen for (T1,T2) {
    fn len(&self) -> usize { 2 }
}
impl<T1,T2,T3> TupleLen for (T1,T2,T3) {
    fn len(&self) -> usize { 3 }
}
impl<T1,T2,T3,T4> TupleLen for (T1,T2,T3,T4) {
    fn len(&self) -> usize { 4 }
}
// etc, etc. Creating a macro would be less repetitive

However, I wouldn't advocate doing this.

5 Likes

To the OP: If you know the "max" number of elements in a tuple (i.e., is there a known boundary limit?), then @chrisd 's solution would be MUCH faster around O(1) time

Well, a struct has fields, so the length should be the number of fields.

Is it possible to convert a tuple to a collection (vector, for instance)? Then getting the size of the collection would yield the result.

If you need to ask this question, it's a sign you probably should be using an array, slice or a Vec.

6 Likes

Tuples are not made to be seen as a sequence or a collection, for that there are arrays (and Vecs).

That being said, you can have a look at ::frunk, it is a crate that thrives on mixing type-level "pseudo-sequences" and runtime sequences (such as arrays or Vecs)

2 Likes

It seems that your code works only for a tuple of strings...

I tried this version but to be sure that funky strings cannot mess things up we would need to use regex and look for ",$" in format!("{:#?}", tuple)

fn get_num<T: std::fmt::Debug + Sized>(tuple: &T) -> usize {
    let s = format!("{:?}", tuple);
    match s.contains(", ") {
        true => {
            let parts = s.matches(", ").collect::<Vec<&str>>();
            parts.len() + 1
        }
        _ => 1,
    }
}
1 Like

Yeah, that looks better!

That's a horrible horrible hack. Please don't seriously use it. Rust doesn't guarantee any particular format of debug output, so even if you fix all the issues with this one, it may still break in the future.
And this hack gives wrong results in most situations beyond simplest tuples of integers (and strings without commas). And it's grossly inefficient for what it does: all the formatting, dynamic allocation, parsing, more allocations. All this just to approximate a value known precisely at compile time.

If you really have to, use this one:

3 Likes

Use my method if your goal is to cause global warming though! #TeamUSA

1 Like

I wasn't planning to use anything like this :wink:

I was just trying out the code and tried to fix a limitation I was seeing. I am very much a rustling myself, so the main goal was to "learn by doing" with this small task.

The message I get is: Use a vec or arrayif you want to know how many items there are. Or a struct, since you define it, so you should know how many items there are.

As others have alluded to, getting the "length" of a tuple isn't very useful because there's not much you can do with it. Assuming for a second that your code compiled as-is, what do you plan on doing with size?

2 Likes

In that statement you have answered your own question, since a tuple is just an anonymous struct with unnamed (though implicitly numbered) fields.

1 Like

Sure. It wasn't my question though. I just played with the code. But it is nice to think about these things. I think the biggest enlightenment comes from wesleywiser's answer (someone may have stated it before/otherwise):

IF you find the length, how will you use it?

1 Like