How to use Result in user-defined function?

Asked

Viewed 44 times

5

Many Rust functions apply the enumerable Result in its implementation. This enumerable makes it easy to manage error, since you can use unwrap or expect to help identify the error in a code.

An example is when you read a file, which may not be in the directory, using std::io::File:

use std::io::File;

fn main () {
    let text = File("hello.txt").expect("Unable to read file");
    println!("{}",text);
}

I would like to know how to implement this in my own functions.

I tried so:

use std::io::Error;

fn main() {
    let s1 = String::from("hello");
    let len = calculate_length(&s1).expect("Please, entry a valid string");
    println!("The length of '{}' is {}.", s1, len);
}

fn calculate_length(s: &String) -> Result<i32, Error> {
    let solution = s.len();
    if solution > 0 {
        return solution;
    } else {
        return Error;
    }
}

Didn’t work.

How do I use the Result in my duties?

  • What is Error?

  • 1

    https://doc.rust-lang.org/std/io/struct.Error.html

  • In this case as the function does not return much relevant information in case of error, maybe use Option also be a good option, using the variant None as representative of the (single) error.

1 answer

5


As stated in the question itself, the Result is an enumeration. In short, the problem is only to return the values that should be "within" the Result. When a enum, should be made clear which of the variants should be used.


In Rust, enumerations allow a single type to assume different meanings, which can be very useful in some situations.

Rust enumerations can "involve" values. For example:

enum Color {
    RGB(u8, u8, u8),
    Hex(String),
}

In that case, the Color accepts values representing colors in RGB and hexadecimal formats.

To create a value like Color, we need to provide the values in the instantiation of the Enum. Thus:

let rgbC = Color::RGB(255, 0, 0);
let hexC = Color::Hex("#3399cc");

Note that it is important to inform the compiler what variant of enum should be used (in the case above, we did this with Color::RGB and Color::Hex). Otherwise, the compiler would not be able to know which variant the programmer refers to, since the only typical information about the enumeration instance is the type of the enum (in the above case, Color).

In the case of Result, the enumeration provides for two possible states: Ok, for success-like cases; and Err, for similar error cases.


Therefore, returning to the example of the question, it is not feasible to return from the function only the value that should be restrained at the instance of enumeration Result.

You must explicitly inform the variant. So:

fn calculate_length(s: &String) -> Result<usize, &'static str> {
    let solution = s.len();
    if solution > 0 {
        return Ok(solution);
    } else {
        return Err("Invalid length.");
    }
}

As the return pattern Result is very common, Rust includes, in the Prelude, beyond the very Result, the names Result::Ok and Result::Err. So instead of typing the "full name" of the variant, you can use the names directly, without the need for the prefix Result::. The same goes for Option, such that Some and None are also available at "global level".


Be sure to read:

Browser other questions tagged

You are not signed in. Login or sign up in order to post.