Explicit and implicit return in functions


#1

Hey gang!

When I read that Rust implicitly returns the last expression in a function! I thought, Oh, Cool! :sunglasses:
I got that, The official style is "return is only for early returns."

But, why is there a choice between explicit and implicit returns. What are the advantages ? :thinking:


#2

It’s purely a stylistic choice so there are no real advantages/disadvantages (other than lowering friction by following established style conventions).

Rust is an expression-oriented language (every chunk of code has a return value, including match, for, etc) so if you’ve got a long string of statements (e.g. a function body) it’s redundant to finish with return foo; when writing foo is just as effective.


#3

one of the advantages, is that in certain situations it makes certain code shorter.
for example, in the code below
there would be at least 5 different places that would need an explicit return
if fields.len() != 5 {
Err(“incorrect number of fields for multiple choice”)
} else {
let answer = convert_choice_to_number(fields[4])?;
let choices : Vec<_> = fields[3].split(’:’).map(String::from)
.collect();

        if choices.len() < 3 {
            Err("not enough choices")
        } else if choices.len() >= 7 {
            Err("too many choices")
        } else if (answer as usize) > choices.len() {
            Err("answer must be a choice")
        } else {
            Ok(MultipleChoice {
                question: String::from(fields[2]),
                choices,
                answer,
            })
        }
    } //outside if
}

well, the official guide doesnt mention it but the borrow checker and immutability by default in addition to being eop based allows rust to wield it self to a more functional style


#4

Thanks for the replies! I can see that its mostly a style choice.

Well, this went straight above my head! Mind breaking down a bit for me ? Thanks!


#5

“Implicit return” gives you the wrong mental model. It’s not an implicit return. It’s that Rust is an expression-based language.

As an expression-based languages, most things are expressions, and expressions evaluate to a value. Blocks are expressions, and so the final value of a block is that block’s value. Functions are blocks.

If Rust truly had “implicit return”, code like this would work:

fn foo(param: bool) -> i32 {
    if param { 5 };

    println!("param is: {:?}", param);

    6
}

But this doesn’t work. You have to use return if you want to produce a value other than the final value of the block.

The official style, then, is to leave off the return in the trailing position because it’s redundant.

Does that make sense?


#6

Thanks for this, now its clear! :slightly_smiling_face:


#7

sorry, eop stands for expression oriented programming.
immutability by default generally lends a lot of rust to be written what some might describe as a “functional style”.
by default you really don’t use side effect generating functions very often because of the two features above