Tom
Tom

Reputation: 5121

How can I get the length of a tuple?

This is the behaviour I tried:

struct Matrix(f32, f32, f32, f32);
let matrix = Matrix(1.1, 1.2, 2.1, 2.2);
matrix.len();    // expected `4`

which produces the error:

error[E0599]: no method named `len` found for type `&tuples::Matrix` in the current scope
  --> src/tuples.rs:19:44
   |
19 |         println!("matrix length: {}", self.len());
   |                                            ^^^
   |
   = help: items from traits can only be used if the trait is implemented and in scope
   = note: the following traits define an item `len`, perhaps you need to implement one of them:
           candidate #1: `std::iter::ExactSizeIterator`
           candidate #2: `core::slice::SliceExt`
           candidate #3: `core::str::StrExt`

std::iter::ExactSizeIterator looks like a good candidate, but I still don't know how to implement it

Context

Whilst trying to reverse Matrix, I realized that instead of dryly listing the reverse indexes of the matrix like so:

fn reverse(matrix: Matrix) -> Matrix {
    return Matrix(matrix.3, matrix.2, matrix.1, matrix.0)
}

I could perhaps iterate over the Matrix in reverse order. I saw How to iterate or map over tuples? and thought that it was complex. If one were able to get the length of the tuple, one could solve the question "How to iterate or map over tuples?" with a simpler solution. Obviously, I could just use '4' as the length, but what if I weren't using a struct but rather a tuple of an unknown length.

Upvotes: 5

Views: 3473

Answers (2)

Idan Geraffi
Idan Geraffi

Reputation: 1

In rust you cant iterate or ask for tuple length. Tuples are implemented in a similar way to struct (anonymous struct if you like). Considering tuple/struct with different types, what is it's length ?

Upvotes: -1

loganfsmyth
loganfsmyth

Reputation: 161607

There are a few ways to approach this question. I'll try to expand as I go.

matrix.len();    // expected `4`

You've defined your own Matrix datatype. With no additional logic, it's entirely up to you to define this, e.g.

impl Matrix {
    fn len(&self) -> usize {
        4
    }
}

Personally I think your reverse function is fine as-is, because it's important to balance DRY with readability, and also differentiate repetition of code with repetition of logic.

The other piece here is that having the length on its own doesn't offer much here. matrix.0 is explicit syntax in Rust, but there's no way to actually use the length to do anything about that. matrix[i] is not an operation you have implemented on your datatype. You can potentially implement that or Iterator for this type, but that doesn't seem like what you'd actually want here. An iterator is a stream of consistent items, but your matrix items have explicit meaning based on their indices that would kind of lose their meaning in the context of an iterator.

I'll also add that you can trim down your reverse using destructuring assignment and auto-return, via

fn reverse(matrix: Matrix) -> Matrix {
    let Matrix(a, b, c, d) = matrix;
    Matrix(d, c, b, a)
}

Upvotes: 2

Related Questions