{"id":1261,"date":"2022-01-20T21:24:05","date_gmt":"2022-01-21T03:24:05","guid":{"rendered":"http:\/\/blog.gwadej.org\/programmer_musings\/?p=1261"},"modified":"2025-09-07T14:06:47","modified_gmt":"2025-09-07T14:06:47","slug":"optional-values-in-rust","status":"publish","type":"post","link":"https:\/\/blog.gwadej.org\/programmer-musings\/2022\/01\/optional-values-in-rust\/","title":{"rendered":"Optional Values in Rust"},"content":{"rendered":"\n<p>Let&#8217;s say we are writing some code to retrieve data from a database. If the data we are looking for is there, we can obviously return it. If there is no data that matches our search, we need to signal that we did not find it. In many languages, we use a <code>nil<\/code>, <code>null<\/code>, or <code>undef<\/code> value as a flag for this missing value. This <em>null reference<\/em> was invented in 1965 by Sir Tony Hoare when designing the type system for the ALGOL W object oriented language. He has since referred to it as his &#8220;billion dollar mistake&#8221;.<\/p>\n\n\n\n<p>Rust does not support a null reference, instead it has the <code>Opti<\/code>on&lt;T&gt; enum. Option has two variants: <code>Some<\/code> which contains the value in question and <code>None<\/code> which means there is no value. If you aren&#8217;t familiar with with Rust&#8217;s enums you might assume that <code>None<\/code> is just a different name for <code>null<\/code>. But, the reality is quite different.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">An Optional Return<\/h2>\n\n\n\n<p>In the example that starts this post, let&#8217;s assume we have a User method that looks up a user by some userid. (We&#8217;ll ignore the actual implementation in this case.)<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>impl User {\n   fn by_id(id: &amp;str) -&gt; Option&lt;User&gt; {\n     ...\n   }\n}<\/code><\/pre>\n\n\n\n<p>Assuming we are supplied an id as a string reference, we look up the user. If we find a user with that id, we return a User object. The value we return is an <code>Option&lt;User&gt;<\/code>. Unlike the null reference case in other languages, we cannot use this value as if it were a <code>User<\/code>, we must extract the value first, which will fail if no <code>User<\/code> was found. One obvious way to extract the value is to use Rust&#8217;s pattern matching.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>match User::by_id(\"gwadej\") {\n   Some(user) =&gt; {\n      \/\/ do work with the user we found\n   },\n   None =&gt; {\n      \/\/ report an error or otherwise handle the missing user case\n   },\n};<\/code><\/pre>\n\n\n\n<p>Obviously, you could do exactly the same thing in another language. But, in Rust, you cannot forget to &#8220;check for the missing user case&#8221;. You could obviously put the result of the User::by_id() method in a variable and pass it around, but eventually, in order to work with the <code>User<\/code>, you will have to resolve whether you actually got a value or not. This solves the problem that all of us see at one point or another where we try to access a value returned elsewhere in the code, find it&#8217;s a <code>null<\/code> and have to backtrack all through the code to find where the <code>null<\/code> came from.<\/p>\n\n\n\n<p>More importantly, since <code>null<\/code> is not a possible value for an object, the only time you have to protect against a missing value is if you receive an <code>Option&lt;T&gt;<\/code>. If a variable or a parameter to a method has an actual type, then it must be a valid value of that type.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Option&lt;T&gt; Methods<\/h2>\n\n\n\n<p>Much like the <code>Result&lt;T, E&gt;<\/code> enum from the last post, using pattern matching to deal with an Option&lt;T&gt; is effective, but verbose. So, Rust provides a number of methods that are useful for common ways of handling missing values.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>let v = opt_int.unwrap_or(42);  \/\/ the value of opt_int or 42 if None\nlet v = opt_int.unwrap_or_default(); \/\/ the value of opt_int or the default value for the type\nlet v = opt_int.unwrap_or_else(good_value); \/\/ the value of opt_int or result of executing good_value()<\/code><\/pre>\n\n\n\n<p>These methods deal with most of the ways you might <em>use a supplied value or a default if not supplied<\/em>.<\/p>\n\n\n\n<p><code>Option<\/code> supports many other <a rel=\"noreferrer noopener\" href=\"https:\/\/doc.rust-lang.org\/std\/option\/enum.Option.html\" target=\"_blank\">methods<\/a>, including <code>map()<\/code> which converts the actual value ignoring a <code>None<\/code>. There are also methods for chaining the generation of multiple <code>Option<\/code>s, allowing you to attempt to retrieve a value from multiple methods, returning the first result that is not <code>None<\/code>.<\/p>\n\n\n\n<p>Also like the <code>Result<\/code>, the question mark operator (<code>?<\/code>) can be applied to an <code>Option&lt;T&gt;<\/code> if the calling function returns an <code>Option&lt;T&gt;<\/code>. The <code>?<\/code> would return the value if any or return <code>None<\/code> if there isn&#8217;t one.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Result and Option<\/h2>\n\n\n\n<p>In some ways, <code>Result&lt;T, E&gt;<\/code> and <code>Option&lt;T&gt;<\/code> are very similar. Both have a success variant and a failed variant. Depending on context, you could see very similar logic used to generate either <code>enum<\/code>. Because of that similarity, each type has methods for converting to the other.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ creates a result that successfully returns the value or returns a error if opt was None\nlet result = opt.ok_or(error_val);\n\n\/\/ like above, but executes make_error to get the error value if None\nlet result = opt.ok_or_else(make_error);\n\n\/\/ discard the error and return the value as an Option&lt;T&gt;.\nlet opt = result.ok();\n\n\/\/ discard the value and return the error as an Option&lt;E&gt;.\nlet opt = result.err();<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Conclusion<\/h2>\n\n\n\n<p>Although the <code>Option&lt;T&gt;<\/code> type is not unique to Rust, it is a very useful way to avoid the need for a <code>null<\/code> reference. The methods supplied by <code>Option<\/code> make it very flexible and convenient. Importantly, the methods on <code>Option<\/code> and <code>Result<\/code> streamline some very common use cases including conversion between the two types.<\/p>\n\n\n\n<p>See the <a rel=\"noreferrer noopener\" href=\"https:\/\/doc.rust-lang.org\/rust-by-example\/std\/option.html\" target=\"_blank\">documentation<\/a> for more details on how <code>Option<\/code>s are used.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Let&#8217;s say we are writing some code to retrieve data from a database. If the data we are looking for is there, we can obviously return it. If there is no data that matches our search, we need to signal that we did not find it. In many languages, we use a nil, null, or\u2026 <span class=\"read-more\"><a href=\"https:\/\/blog.gwadej.org\/programmer-musings\/2022\/01\/optional-values-in-rust\/\">Read More &raquo;<\/a><\/span><\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[13],"tags":[223,227,235,286,294],"_links":{"self":[{"href":"https:\/\/blog.gwadej.org\/programmer-musings\/wp-json\/wp\/v2\/posts\/1261"}],"collection":[{"href":"https:\/\/blog.gwadej.org\/programmer-musings\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.gwadej.org\/programmer-musings\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.gwadej.org\/programmer-musings\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.gwadej.org\/programmer-musings\/wp-json\/wp\/v2\/comments?post=1261"}],"version-history":[{"count":1,"href":"https:\/\/blog.gwadej.org\/programmer-musings\/wp-json\/wp\/v2\/posts\/1261\/revisions"}],"predecessor-version":[{"id":1379,"href":"https:\/\/blog.gwadej.org\/programmer-musings\/wp-json\/wp\/v2\/posts\/1261\/revisions\/1379"}],"wp:attachment":[{"href":"https:\/\/blog.gwadej.org\/programmer-musings\/wp-json\/wp\/v2\/media?parent=1261"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.gwadej.org\/programmer-musings\/wp-json\/wp\/v2\/categories?post=1261"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.gwadej.org\/programmer-musings\/wp-json\/wp\/v2\/tags?post=1261"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}