I am trying to get into Rust by learning it from its book. Mostly common things with interesting additions on it. I try to code some stuff to get used to it so I decided to do as the chapter says and write a quick Fibonacci function but had an error I am having problems wrapping my head around. Any rust expert who would explain to me why is this happening and the logic behind it.
fn fibo(x: i32) -> i32 {
if x == 0 {
0
}
else if x == 1 {
1
}
fibo(x-1) + fibo(x-2)
}
When I try to build this code, I get the following error;
error[E0308]: mismatched types
--> src/main.rs:6:9
|
6 | 0
| ^ expected (), found integer
|
= note: expected type `()`
found type `{integer}`
error[E0308]: mismatched types
--> src/main.rs:9:9
|
9 | 1
| ^ expected (), found integer
|
= note: expected type `()`
found type `{integer}`
But If I change the code to the following it works fine;
fn fibo(x: i32) -> i32 {
if x == 0 {
0
}
else if x == 1 {
1
}else{
fibo(x-1) + fibo(x-2)
}
}
In the Rust Language book, it is stated that the compiler checks the type of all the expressions in the if-else blocks but also states that it passes to the next line of code if there is no else statement is present. Since I stated the return type would be i32 how come the compiler can expect type "()" as seen in the error?
The problem here is that you're trying to have two "return" statements.
When a block's last statement lacks a semicolon, the result of the statement is the type of evaluating the entire block. In pseudo-rust, we can say the following
{
0
} -> usize
That's to say
let x = { 0 };
Makes a new scope for the 0
, implicitly returns it because there's no semicolon in the block, and then that becomes the type of the block. So, x: usize
.
So, what's going on?
Your code has two implicit returns:
fn fibo(x: i32) -> i32 {
if x == 0 { // This starts a block
0 // First implicit return
}
else if x == 1 { // This also starts a block
1 // First implicit return
} // Therefore this entire if/else statement is an implicit return unless its output
// is suppressed with a semicolon.
fibo(x-1) + fibo(x-2) // Here we try to return again, which confuses rust!
}
Because your if/else
contains implicit returns and is not being assigned to a variable, it is like as if I said the following:
fn fibo(x: i32) -> i32 {
//For the sake of explanation, let's assume x == 0
0 // instead of your if/else
fibo(x-1) + fibo(x-2)
}
Oh no! How to fix this:
fn fibo(x: i32) -> i32 {
if x == 0 {
// return 0; // This is an early return; this will break until it reaches the function
0 // Since this is about implicit returns I'll use them here
} else if x == 1 {
1
} else {
fibo(x - 1) + fibo(x - 2)
}
}