There's quite a few changes you did to the code, and they result in a handful of unrelated and different kinds of errors.
Let’s start off by applying consistent formatting to both code examples and let's re-order the two functions so the order stays the same. (The order in which functions are defined in Rust does not matter, so this change will not change any of the errors we get.)
fn main() {
let arr = [1, 2, 3, 4, 5];
rev_numbers(arr);
}
fn rev_numbers(arr: [i64; 5]) {
for i in arr.iter().rev() {
println!("{}", i);
}
}
fn main() {
rev_numbers(arr);
}
fn rev_numbers(arr: &[i64]) -> Option<i64> {
let arr = vec![1, 2, 3, 4, 5];
for i in arr.iter().rev() {
println!({}, i);
}
}
Comparing, we can spot that 4 things changed.
- the
let arr = …
line moved from main
into ref_numbers
- the argument type of
rev_numbers
changed from [i64; 5]
to &[i64]
- the function didn't have any return type and now got
-> Option<i64>
return type added to its signature
- the
println!("{}", i)
expression was changed into println!({}, i)
Now, the last change in println
creates the first error; using {}
instead of "{}"
is simply a syntactical error… perhaps a typo? The error message “format argument must be a string literal” hints that the first thing in the println!(…)
call must be a so-called string literal, which is some text between double quotes. (It must also furthermore be a “format string”, see here for more info.)
The second error comes from the first change, the arr
variable is no longer a variable defined in main
but in rev_numbers
. But in rev_numbers
, there also is a function argument called arr
which will get overridden (aka “shadowed”) by this definition, whereas in main
, arr
does no longer exist at all. The latter effect, that arr
does no longer exist in main
, even though it is used in the call to rev_numbers
is an error that manifests, as the compiler calls out ”cannot find value `arr` in this scope“.'
Next, the last error message obviously relates to the changed return type, -> Option<i64>
, as the error message contains a hint that prominently points there
1 | fn rev_numbers(arr: &[i64]) -> Option<i64> {
| ----------- expected `Option<i64>` because of return type
What this is telling us is that the function signature now claims that a value (of type Option<i32>
) is returned from rev_numbers
, but the function implementation remains unchanged and actually still returns no value. The error message is slightly more technical in that it refers to the type “()
”, aka the “unit” type which is a useful type of values that are really no value at all.
Like a number zero that refers to the number of things when there’s no things at all; or the word “nobody” that can form sentences involving a subject and some action, e.g. “nobody dances”, but the meaning is actually that dancing does not happen at all.
Anyways… back to Rust, like our wish to be able to give every situation, even when there’s nothing there, a number, or to give every possibility of who dances, even if dancing doesn’t even happen, a uniform way of talking about it, every Rust function has a return type and returns something, in principle, and functions that don’t really return anything in practice thus get to return a “value”, the type ()
, so this type is (among perhaps a few other uses we won’t discuss) the return type of functions that don’t return anything. You could more explicitly call out this fact by re-writing the old function signature
fn rev_numbers(arr: [i64; 5]) {
into the identical, yet differently written, signature
fn rev_numbers(arr: [i64; 5]) -> () {
And now, the change was from -> ()
into -> Option<i32>
, without the necessary change to the function implementation to also return a Option<i32>
value, it still returns nothing, i.e. implicitly returns a value of type ()
, and the error message tells you “hey, there’s a problem, ()
is not the same as Option<i32>
”
error[E0308]: mismatched types
…
= note: expected enum `Option<i64>`
found unit type `()`
For comparison, the code example that @quinedot had given you in this answer did also feature a return value:
fn max_number(numbers: &[i64]) -> Option<i64> {
let mut large = numbers.get(0)?;
for number in numbers {
if large < number {
large = number
}
}
Some(*large)
}
the last line of a function, if it doesn’t end with “;
”, is the return value, the effect in the above function is similar to something written more like
fn max_number(numbers: &[i64]) -> Option<i64> {
let mut large = numbers.get(0)?;
for number in numbers {
if large < number {
large = number
}
}
return Some(*large);
}
in other programming languages without such implicit returns.
With this in mind, the suggestion the compiler gave you should make sense; it suggested adding a line with None
or Some(…)
to actually return a value from the function and fix the error.
Overall, while the compiler output was lengthy, I would suggest you have a deeper look back into these error messages. The compiler error messages for Rust are generally very useful. You can save yourself and others some time with every compiler error messages that you understand yourself. Reading error messages in Rust completely, i.e. every single line of the message, can find all the necessary information to fix the problem, or at least progress with the fix. If this isn’t the case for you yet anyways, try to practice becoming better with error messages and try to relate e.g. my answer in this forum to the error message you got, in order to have a higher change of understanding similar error messages in the future 
For example the error about println!
was probably just a typo, and comparing the changes you made in the code, it should have been easy to spot the problem yourself… well, unless you just overlooked the ""
s and didn’t know what a “string literal” is. But then perhaps at least you will know in the future.
By the way, there was a 4th change that didn’t result in an error yet, but will if you resolve the other problems: From the list above, the changed function argument type (into &[i64]
) is something we did not talk about yet. If you manage to fix the other issues, you might thus run into an error such as
mismatched types
with additional information
expected `&[i64]`, found array `[i64; 5]`
In case that happens, read the whole message, pay attention to hints such as ”help: consider borrowing here: `&arr`
“ that might appear, and perhaps compare your code to the one in @quinedot's example code, to find an approach to address the problem.
As a final nit pick: Note that you are using the term “generic function” incorrectly in your question in the context of Rust. The term “generic function” typically refers to functions with generic type arguments, which are described in this chapter in the book.
Of course, this usage of the term “generic” is specific to certain programming languages, including Rust, and outside of these contexts, abstracting functionality in a function in and by itself can be described reasonably, to be “generic” in some sense. But you should avoid using the term “generic” like that in the context of Rust, since that would confuse people accustomed to the technical meaning of the term, referring to generic type arguments.