42

What is the closest equivalent Rust code to this Python code?

a, b = 1, 2 a, b = b, a + b 

I am trying to write an iterative Fibonacci function. I have Python code I want to convert to Rust. Everything is fine, except for the swap part.

def fibonacci(n): if n < 2: return n fibPrev = 1 fib = 1 for num in range(2, n): fibPrev, fib = fib, fib + fibPrev return fib 
3

2 Answers 2

57

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:

Sign up to request clarification or add additional context in comments.

2 Comments

can you elaborate on when someone would want to change things in place vs re-binding the variables? Also, what's wrong with creating new bindings? Not efficient?
@No_name You can't re-bind in a loop (well, you can, but the new values will be lost on the next iteration). So for example it can't be (directly) used for calculating the factorial.
6

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.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.