Welcome to module 8,
Useful methods on
result and option.
In this module,
we're going to cover the most useful methods
the Standard Library has defined on
Result and Option.
We'll see how to test for which variant we have,
how to convert a Result to an Option
and vice versa,
how to specify a fallback value
to use in the error
and None cases,
and how to transform the Ok
or Some values further,
but leave error or None values as they
are.
Let's start with testing to see which variant
we have.
The names of these methods are different
for the two types.
Result has the methods is_ok
and is_err for testing
whether a value of type Result
is the Ok variant or the Err
variant.
Option has the methods is_some
and is_none that test whether
a value is the Some variant
or the None variant.
These methods are useful when you want
to know which variant you have,
but either don't want to or can't
test what the values within the variants
are.
These tests could be asserts
in automated tests
or in conditionals used for control flow.
These methods shouldn't be used in
combination
with unwrap -
the method that returns the inner value
of an Ok or Some
and panics otherwise.
An example of this antipattern
is checking if a value is some
and unwrapping it if so.
Yes, this ensures the unwrap
won't cause a panic,
but the code isn't very clear.
You'd have to read this code carefully to
notice that it won't panic.
The code is also doing a redundant check
of which variant the value is.
A better choice with regards to code readability
and runtime performance would be to
use match, if let,
or one of the methods we'll be covering in the
rest of the module.
Next,
let's talk about converting between Result
and Option.
To convert a Result into an Option,
you can use the ok method.
If you call ok on an
Ok value, you'll get
a Some variant holding the same
value that the Ok was holding.
If you call ok on an Err
value,
you'll get a None variant,
and the value inside the error will be
thrown away.
To convert an Option into a Result,
you can use the ok_or
method.
If you call ok_or
on a Some value,
you'll get an Ok variant holding the same
value that the Some was holding.
When we converted from Result to Option,
we lost the error information,
which means to convert from Option to Result,
we need to add information -
the error value that None should correspond
to.
That's what the argument to
ok_or is.
If the value is None, calling
ok_or will return the argument
inside an Err variant.
Next, let's talk about specifying
fallback values by using the
unwrap_or method.
If called on Ok
or Some,
unwrap_or extracts the value
from the variant,
and returns that
so you can use it.
If called on Err
or None,
unwrap_or returns the fallback
value specified as an argument.
For example, in the module where
we introduced Result and Option,
we tried to parse JSON that may
or may not be valid.
We used the match expression to return
a fallback Person value,
if there is an error.
Instead of the match,
we can use unwrap_or
and specify the fallback
value.
We can shorten this code further
using the
unwrap_or_default method.
This method doesn't take an argument
but always uses the type's
default value.
It makes use of the functionality defined
by the Default trait
and otherwise has the same behaviour as
unwrap_or.
So, if the type inside the Ok
derives or implements the Default trait,
you can use the
unwrap_or_default method.
Next, let's talk about a method
that lets us transform Ok
or Some values further.
This method is called map.
It's useful when you want to perform an
operation on the value in
Ok or Some.
But leave Err
or None values as they are.
Here's a simplified example
from crates.io code.
We have a Version struct that may
or may not have the id of the
user who published that crate version
because we only recently started tracking
that information.
To get the User struct that goes
with the user ID in the version,
we've defined the published_by method
that has the return type Option.
If the version's published_by attribute
is the Some variant,
meaning it has an ID,
we use map to look up the user
in the database.
If published_by is None,
the map does nothing
and passes the None value through.
We've provided simplified definitions
for the User struct
and the user find function
so that we can run this main function
that creates a version that has the
user id
and a version that doesn't.
When we run this code,
we see the result of calling map
is Some(User struct instance
if published by is Some,
and None if published by is None.
There are many more methods defined on
Result and Option than we can
cover in this video.
Lots are slight variations on the ones
we have touched on,
such as methods that take a closure to
apply,
rather than a value
or vice versa.
By learning about some of these methods,
you now have a good idea of what many
of them do.
Overall, if you find yourself writing
a match expression to handle a Result
or Option,
and the match feels like it's a common operation
many people would want to do,
check the documentation to see if there is a method
that does what you're doing by hand.
In this module,
we discussed a bunch of useful methods on
Result and Option.
We covered how to test which variant you
have,
with is_ok,
is_err, is_some,
and is_none.
We showed how to convert results to options
with ok,
and options for results
with okay_or.
We talked about specifying fallback values
with unwrap_or
and unwrap_or_default.
And we looked at transforming values within
Ok or Some
using the map method.
That's the end of the Error Handling unit.
Next unit,
we'll learn all about lifetimes.