How to swap two variables?
When swapping variables, the most likely thing you want is to create new bindings for a
and b
.
fn main() {
let (a, b) = (1, 2);
let (b, a) = (a, a + b);
}
For your actual case, you want to modify the existing bindings. Rust 1.59 will stabilize destructuring assignment:
fn fibonacci(n: u64) -> u64 {
if n < 2 {
return n;
}
let mut fib_prev = 1;
let mut fib = 1;
for _ in 2..n {
(fib_prev, fib) = (fib, fib + fib_prev);
}
fib
}
Before Rust 1.59, you can use a temporary variable:
fn fibonacci(n: u64) -> u64 {
if n < 2 {
return n;
}
let mut fib_prev = 1;
let mut fib = 1;
for _ in 2..n {
let next = fib + fib_prev;
fib_prev = fib;
fib = next;
}
fib
}
You could also make it so that you mutate the tuple:
fn fibonacci(n: u64) -> u64 {
if n < 2 {
return n;
}
let mut fib = (1, 1);
for _ in 2..n {
fib = (fib.1, fib.0 + fib.1);
}
fib.1
}
You may also be interested in swapping the contents of two pieces of memory. 99+% of the time, you want to re-bind the variables, but a very small amount of time you want to change things "in place":
fn main() {
let (mut a, mut b) = (1, 2);
std::mem::swap(&mut a, &mut b);
println!("{:?}", (a, b));
}
Note that it's not concise to do this swap and add the values together in one step.
For a very concise implementation of the Fibonacci sequence that returns an iterator:
fn fib() -> impl Iterator<Item = u128> {
let mut state = [1, 1];
std::iter::from_fn(move || {
state.swap(0, 1);
let next = state.iter().sum();
Some(std::mem::replace(&mut state[1], next))
})
}
See also:
- Can I destructure a tuple without binding the result to a new variable in a let/match/for statement?
- How can I swap in a new value for a field in a mutable reference to a structure?
In addition, a better way to implement the Fibonacci sequence in Rust is using the Iterator
trait:
// Iterator data structure
struct FibIter(u32, u32);
// Iterator initialization function
fn fib() -> FibIter {
FibIter(0u32, 1u32)
}
// Iterator trait implementation
impl Iterator for FibIter {
type Item = u32;
fn next(&mut self) -> Option<u32> {
*self = FibIter(self.1, self.1 + self.0);
Some(self.0)
}
}
fn main() {
println!("{:?}", fib().take(15).collect::<Vec<_>>());
}
See The Rust Programming Language chapter on iterators.