How do I do on-site assignments in Rust?

In C ++, I can do in-place assignments that increment a variable var

as it is printed to the screen:

int var = 5;
std::cout << ( var += 1 ) << std::endl;

      

I do this because Rust doesn't have in / decment ++

and --

. I tried this in Rust:

let mut counter = 0;
println!("{}", (counter += 1));

      

They say:

error[E0277]: the trait bound `(): std::fmt::Display` is not satisfied
 --> src/main.rs:3:20
  |
3 |     println!("{}", (counter += 1));
  |                    ^^^^^^^^^^^^^^ the trait `std::fmt::Display` is not implemented for `()`
  |
  = note: `()` cannot be formatted with the default formatter; try using `:?` instead if you are using a format string
  = note: required by `std::fmt::Display::fmt`

      

-1


source to share


2 answers


Rust's assignment operators do not evaluate the assigned value; they are evaluated before ()

. Therefore, you need to read the variable after assignment to get the new value. You can do this with a block, since blocks are also expressions.

let mut counter = 0;
println!("{}", { counter += 1; counter });

      



If you are going to do this often, consider defining a macro:

macro_rules! inc {
    ($e:expr) => {
        { $e += 1; $e }
    }
}

let mut counter = 0;
println!("{}", inc!(counter));

      

+5


source


The shortest solution is to return a value:

let mut counter = 0;
println!("{}", {counter += 1; counter});

      

But to be honest, I would say that this is not idiomatic Rust and you can just write it on a different line:

let mut counter = 0;
counter += 1;
println!("{}", counter);

      


The longer answer is that you cannot get the assignment value. The characteristic is AddAssign

defined as

pub trait AddAssign<Rhs = Self> {
    fn add_assign(&mut self, Rhs);
}

      

In particular, there is no return value from the method. Rust has no useful effect on the outcome of the assignment, because in general it does not. Ownership semantics make it difficult to define what should be the "return value" of something let x = String::new();

. If it were String

, what would happen to the possession enclosed in x

?



Since all expressions return some type, assignments return an empty tuple ( ()

), also known as the type of unit.

In this case, the value is an integer that implements the property Copy

. This means that you can trivially return a copy from a block.

The same solution will "work" for String

until you try to use it afterwards:

let mut string = String::new();
println!("{}", {string += "a"; string});
println!("{}", string); // use of moved value: `string`

      

What can be fixed by returning a link:

println!("{}", {string += "a"; &string});

      

But at the moment there is no "savings".

+4


source







All Articles