What is the point of using Option as a type in the argument of a function?

Asked

Viewed 48 times

3

I’m trying to use a function that has as argument a variable of type Option.

An example without Option:

fn main() {
    next10(9);
}

fn next10(n: i32) {
    for i in n..n+10 {
        println!("{}", i)
    }
}

An example with Option:

fn main() {
    next10(Some(9));
}

fn next10(n: Option<isize>) {
    let k = n.unwrap();
    for i in k..k+10 {
        println!("{}", i)
    }
}

What bothered me here is having to use the Some every time you use the function that has a type Option as an argument.

What is this used for? There is a more "clean" way (without the Some) to use such functions?

  • 1

    In this case I confess that I could not see justification for use, even more using the unwrap... Where did this example come from?

  • I tried to create an example to replicate the problem I had using the implementation head of the struct DataFrame polars: https://docs.rs/polars/0.12.1/polars/frame/struct.DataFrame.html#method.head

  • I tried to pass the whole number and was giving error. Then I saw that I can using Some, what seemed to me very cumbersome

1 answer

3


If you don’t like it and don’t need it, don’t use it. You almost always don’t need it. But if you use it, you have to pay the price the engine charges. Everything is tradeoff in computing.

When you create a type like this you need to initialize its value in some way, and Rust everything needs to be explicit, besides not having a constructor the way we know it in other languages, then we have factory methods to create a valid value, so somehow you have to tell the type you’re creating, even for the inference to work when it’s used. The Some() is this method that takes a default value of another type and creates an object of the type Option.

It’s even possible not to do what you are already having an object Option ready to use from somewhere. And usually it is in these cases that you should have a receiving parameter Option.

If you know other languages you must understand the concept of annulable types. Some in one way, others in another, but the general idea is that a type can have a natural value of that object or a null value.

This pattern is considered the 1 billion dollar mistake, and more modern languages avoid this by not allowing the null value.

But how to solve the question when an invalid value for the object is needed for the semantics of the problem? That is, how to resolve when a value may exist or not according to the definition of the domain you are working on?

Simple, use a special type that has the value or an indicator that has no value. This type is the Option.

If you receive an object that can be one Option almost always should wear a Pattern matching to decide what to do when it has a value or when it does not. Possibly another form of selection about the Some and the None can solve.

Simply making a mistake does not seem like a very correct idea (but there are always exceptions), and seems to abuse the use of panic (which is the equivalent of abuse of exceptions from other languages). In general the most correct would usually be to return a Result indicating the error. But the most correct would still be not receiving the Option in this case because you have nothing to do if an invalid die comes. It’s what I always say so as not to catch exceptions when you can’t do anything useful.

This is a clear case of using the mechanism only to demonstrate it in action, not to show its usefulness. There was no gain in this code to put this parameter.

A good use could be if the value None would require to accomplish something, such as generating a Result, already spoken, send a message to the user (if this is pertinent, is a UI method), generate a log, execute a specific action because it does not have a valid value, that is, the invalid value can be treated in a useful way. Ignore the None indicates that this object should not be received.

Browser other questions tagged

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