18

I'm writing a function to read vectors from stdin, and here is what I have so far:

fn read_vector() -> (i64, i64, i64) {
    let mut vec = (0, 0, 0);
    let mut value = String::new();

    for i in 0..3 {
        io::stdin().read_line(&mut value).expect("Failed to read line");
        vec.i = value.trim().parse().expect("Failed to read number!"); // error!
    }
}

However, the annotated line contains an error:

error: no field `i` on type `({integer}, {integer}, {integer})`
  --> src/main.rs:13:13
   |
13 |         vec.i = value.trim().parse().expect("Failed to read number!");
   |             ^

Reading the documentation entry doesn't reveal any get, or similar function.

So, is there any way to get the ith value of a tuple?

Rakete1111
  • 47,013
  • 16
  • 123
  • 162

3 Answers3

34

There isn't a way built in the language, because variable indexing on a heterogeneous type like a tuple makes it impossible for the compiler to infer the type of the expression.

You could use a macro that unrolls a for loop with variable indexing for a tuple if it is really, really necessary though.

If you are going to be using homogeneous tuples that require variable indexing, why not just use a fixed-length array?

EvilTak
  • 7,091
  • 27
  • 36
  • 1
    i just got really used to using parenthesis for everything in other languages. which is why i was using tuples instead of arrays. honestly it is just that simple. it helps having clear explanations like this, so thanks. – don bright Jul 13 '18 at 01:01
  • "You could use a macro that unrolls a for loop with variable indexing for a tuple" - how would one do this? It's possible to [count with a macro](https://danielkeep.github.io/tlborm/book/blk-counting.html), but [tuple indices must be literals](https://doc.rust-lang.org/reference/tokens.html#tuple-index), yet it looks like it's [impossible to evaluate expressions in a macro](https://stackoverflow.com/questions/49576878/how-do-i-evaluate-expressions-in-rusts-macro-system), let alone compute an expression into a literal... – ForceBru Oct 23 '20 at 14:19
  • @ForceBru I should have been more clear, but this can best be achieved by writing a [function-like procedural macro](https://doc.rust-lang.org/reference/procedural-macros.html#function-like-procedural-macros). As you mentioned, this would be pretty difficult to do via a conventional macro by example. – EvilTak Oct 23 '20 at 16:39
8

So, is there any way to get the ith value of vec?

No, there isn't. Since tuples can contain elements of different types, an expression like this wouldn't have a statically-known type in general.

You could consider using an array instead of a tuple.

fjh
  • 12,121
  • 4
  • 46
  • 46
2

While there are no built-in methods to extract the i-th value for non-constant i, there exist crates like tuple to implement dynamic indexing of a homogeneous tuple.

extern crate tuple;

...
*vec.get_mut(i).unwrap() = value.trim().parse().expect("!");

(But, as @fjh mentioned, it is far better to operate on an array [i64; 3] instead of a tuple (i64, i64, i64).)

Community
  • 1
  • 1
kennytm
  • 510,854
  • 105
  • 1,084
  • 1,005