What's the difference between returning Ok(()); and Ok(())

fn dispatch<Tx>(&mut self, tx_token: Tx, timestamp: Instant,
                    packet: ip::Packet) -> Result<()>
{
    Ok(())//works
    Ok(());//won't work
}

why without the semicolon it works? By the way, what () means? Why some functions return Result<()> instead of simple Result?

First, about Ok(()) vs Ok(());. The first thing is an expression, which evaluates to itself; the second is only statement. When the last statement in the block (including function body) is an expression, the block will evaluate to this expression; if the last statement is not an expression, however, block evaluates to unit, which is not of type Result<()>.

Second, about Result. This is generic type, with - in the most common form - two parameters: the "success type" and the "error type", which must always be substituted. You are most likely using something like io::Result, which is the common Result with fixed error type, so that you have to fill in only the "success" type - but you still have to fill it in. And here the unit type, written as (), comes into play: it is a type of values which are not really values. It simply serves as a mark that the program reached some state, in this case - that the function returned successfully.

where can I read more about the difference between putting a semicolon and not?

There is some discussion in the Functions section of the book:

Let’s look at another example:

Filename: src/main.rs

fn main() {
    let x = plus_one(5);

    println!("The value of x is: {}", x);
}

fn plus_one(x: i32) -> i32 {
    x + 1
}

Running this code will print The value of x is: 6 . But if we place a semicolon at the end of the line containing x + 1 , changing it from an expression to a statement, we’ll get an error.

Filename: src/main.rs

fn main() {
    let x = plus_one(5);

    println!("The value of x is: {}", x);
}

fn plus_one(x: i32) -> i32 {
    x + 1;
}

Compiling this code produces an error, as follows:

$ cargo run
   Compiling functions v0.1.0 (file:///projects/functions)
error[E0308]: mismatched types
 --> src/main.rs:7:24
  |
7 | fn plus_one(x: i32) -> i32 {
  |    --------            ^^^ expected `i32`, found `()`
  |    |
  |    implicitly returns `()` as its body has no tail or `return` expression
8 |     x + 1;
  |          - help: consider removing this semicolon

error: aborting due to previous error

For more information about this error, try `rustc --explain E0308`.
error: could not compile `functions`.

To learn more, run the command again with --verbose.

The main error message, “mismatched types,” reveals the core issue with this code. The definition of the function plus_one says that it will return an i32 , but statements don’t evaluate to a value, which is expressed by () , an empty tuple. Therefore, nothing is returned, which contradicts the function definition and results in an error. In this output, Rust provides a message to possibly help rectify this issue: it suggests removing the semicolon, which would fix the error.

In short, if you leave off the semi-colon it "returns" the value to the outer scope. In this context:

fn func() -> Result<()> {
    Ok(())
}

Is equivalent to

fn func() -> Result<()> {
    return Ok(());
}

But note that this isn't always the same as using the return statement. For example:

let value = if result.is_ok() {
    42
} else {
    0
};
// `value` is now either 42 or 0.

Here the numbers are "returned" from the if statement. But unlike the return statement it doesn't cause the function to return.

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.