1

Hello fellow Rustaceans! How it is possible that i can write that in Rust:

let mut v : Vec<u8> = Vec::new();
v.push(0);
v.push(1);
v.push(2);
let s = &v;
print!("{:?} - ", s); // will output "[0, 1, 2]"
let s = &v[1..];
println!("{:?}", s); // will screen "[1, 2]"

Normaly variables are immutable by default, no ? And here i can change the value of the slice (s) but normaly s is declared than variable with "let" ? what's wrong ?

Lionel G
  • 457
  • 6
  • 10
  • 6
    You don't change `s`: you declare another `s`. Reusing a variable name (which shadows the first one) is totally valid in Rust but isn't akin to mutation. – Denys Séguret May 28 '21 at 20:06
  • This is strange comportment because if i inject the first "s" in a threaded function ( the output take some seconds to be disponible) and the second (re) affectation "s" in another threaded function and i would sum (by example) the two output, the result will be wrong ! however perhaps rust will block this two affectation on compilation ? – Lionel G May 28 '21 at 20:52
  • But your answer is fully logic and comprehensive, i think that is the compiler will block the this two affectation on compilation. thanks to you ! – Lionel G May 28 '21 at 20:57

1 Answers1

2

As pointed out in the comments, you're making a new variable called s. Up to renaming, your code is equivalent to

let mut v : Vec<u8> = Vec::new();
v.push(0);
v.push(1);
v.push(2);
let s = &v;
print!("{:?} - ", s); // will output "[0, 1, 2]"
let my_unrelated_s_variable = &v[1..];
println!("{:?}", my_unrelated_s_variable); // will screen "[1, 2]"

The two s you declared are, as far as the Rust compiler is concerned, unrelated variables. In fact, we could even give the second one a different type.

let s = &v;
let s = 42; // This one's an integer, but it's fine

This sort of shadowing is very common in Rust when we want to augment a particular value but want to respect immutability, as it guarantees we aren't actually changing anything in memory while allowing us the convenience of reusing variable names. For example, I often find myself doing things like this.

fn example(input: &str) {
  let input = some_complicated_parsing_step(input)?;
  ...
}

The argument input is a string, and I want to convert it to something (maybe parse it as JSON, maybe read an integer from it, etc.). Once I do that, I have no use for the original string anymore, and it's reasonable to call the result of parsing input, as it is still the input I was given, just in a different form now.

Silvio Mayolo
  • 62,821
  • 6
  • 74
  • 116
  • This is strange comportment because if i inject the first "s" in a threaded function ( the output take some seconds to be disponible) and the second (re) affectation "s" in another threaded function and i would sum (by example) the two output, the result will be wrong ! however perhaps rust will block this two affectation on compilation ? – Lionel G May 28 '21 at 20:50
  • But your answer is fully logic and comprehensive, i think that is the compiler will block the this two affectation on compilation. thanks to you ! – Lionel G May 28 '21 at 20:57
  • fn example(input: &str) { let input = some_complicated_parsing_step(input)?; ... } What you describe here is called "transtyping" in other programming languages that's right ? Thanks ! – Lionel G May 28 '21 at 21:19