Why is using return as the last statement in a fun

2020-02-11 17:43发布

I was reading through the Rust documentation and came across the following example and statement

Using a return as the last line of a function works, but is considered poor style:

fn foo(x: i32) -> i32 {
    if x < 5 { return x; }

    return x + 1;
}

I know I could have written the above as

fn foo(x: i32) -> i32 {
    if x < 5 { return x; }

    x + 1
}

but I am more tempted to write the former, as that is more intuitive. I do understand that the function return value should be used as an expression so the later works but then why wouldn't the former be encouraged?

标签: rust
3条回答
太酷不给撩
2楼-- · 2020-02-11 17:59

Copied from reddit: Why isn't the syntax of return statements explicit?


Answer from @pcwalton

Explicit return is really annoying in closures. For example, it was a major pain in JavaScript before ES6 arrow functions were introduced

myArray.map(function(x) { return x * 2; })

is gratuitously verbose, even without the function keyword. Once you have implicit returns somewhere in your language, you might as well have them everywhere for consistency's sake. The fact that it makes code less verbose is just an added bonus.

and from @mozilla_kmc

Rust is an expression-oriented language. A block has the form

{
    stmt;
    stmt;
    ...
    stmt;
    expr
}

The statements are (basically) expressions or let bindings, and the trailing expression is implicitly () if not specified. The value of the whole block is the value of this last expression.

This is not just for functions. You can write

let foo = if x { y } else { z };

so if also takes the place of C's ?: operator. Every kind of block works the same way:

let result = unsafe {
    let y = mem::transmute(x);
    y.frob()
};

So the implicit return at the end of a function is a natural consequence of Rust's expression-oriented syntax. The improved ergonomics are just a nice bonus :)

Puzzle: return x itself is an expression -- what is its value?

Answer:

It is unit type ().

查看更多
来,给爷笑一个
3楼-- · 2020-02-11 18:02

It just is.

Conventions don’t need to have particularly good reasons, they just need to be generally accepted conventions. As it happens, this one does have a comparatively good reason—it’s shorter as you don’t have the return and ;. You may think that return x + 1; is more intuitive, but I disagree strongly—it really grates and I feel a compelling need to fix it. I say this as one who, before starting using Rust, had never used an expression-oriented language before. While writing Python, return x + 1 in that place looks right, while writing Rust it looks wrong.

Now as it happens, that code should probably be written thus instead:

fn foo(x: i32) -> i32 {
    if x < 5 {
        x
    } else {
        x + 1
    }
}

This emphasises the expression orientation of the language.

查看更多
何必那么认真
4楼-- · 2020-02-11 18:11

The clippy lint gives the following rational for the needless_return lint:

Removing the return and semicolon will make the code more rusty.

This is probably as good as an objective rationale as we will ever get.

As far as intuition goes; I feel that it is shaped by our individual experiences and therefore subjective. While Rust is not a functional programming language itself, many people using and developing it seem to have a strong background in functional programming languages like Haskell, which are entirely based on expressions. The influence can be strongly felt in many areas of Rust (e.g. error handling). So for them (and to be honest, myself included) using an expression instead of a statement seems more elegant.

查看更多
登录 后发表回答