Hi! I am new to rust and have a simple question about: Some()


#1

I have been through the tutorials and have seen Some used (I may have missed the introduction to it, but I don’t think so…), but I do not have a firm grasp of what it does. Would anyone mind a second to give me a couple examples of what it is telling the compiler to do with a given value? Some uses like an explanation of below?

An example from the doc:

let mut x = Some(2);
match x.as_mut() {
    Some(v) => *v = 42,
    None => {},
}
assert_eq!(x, Some(42));

Thanks for your time!
Matt


#2

Some(T) is one of the variants of Option (https://doc.rust-lang.org/std/option/enum.Option.html). That means, Option can take two forms, each of them called a variant.

Option encodes the (expected) presence or absence of a value. Some(T) is the variant that says “there is a value of type T”, None says “there is no value”. This is kind of similar to the concept of having null or a pointer to a value.

Rust doesn’t allow you to have any arbitrary value being absent though, like for example Java does (anything can be null). Rust forces you to actually declare that (by using Option<T> instead of T and to unwrap that condition: you have to check for Option being Some(T) or None before working with the (possible) contents. Through that, it achieves safety and points where other languages would throw NullPointerException.

If the alternative of a value not being available is the result of an error and not expected in normal operation, you should use Result instead.


#3

So Some(T) is saying give me the value T points to or null? Ok I think that is starting to click. Time to go play with it a bit see if I can cement the concept in place. Thank you for your response!


#4

There are two different way you can use Some(x). One is in the line

let mut x = Some(2);

This constructs a value of type Option<int> [1]. You are creating a “box” around the integer. Why would you do that? Well, it allows you to have one more value than a simple integer: None. So you can pass optional values around without having to designate a perfectly fine integer value (like -1 in many cases in C) that is “special” and stands for “error” or “impossible”.

The other use is in the line

match x.as_mut() {
    Some(v) => *v = 42,
    None => {}

This deconstructs the value again, giving you back the contents of the Some box – but you have to handle the None case as well! (The as_mut() makes it a bit more complicated: it gives you not the contents of the original “box”, but a mutable reference to it.)

So, in expressions Some() constructs a value, in patterns in deconstructs a value.

[1] int here can stand for different integer types, since you only use literals, but that doesn’t matter here.


#5

I think it clicks if you avoid saying null. It’s similar, but not quite the same. null (for most) describes the actual use of a null pointer. None has no pointer semantics, but is just the case where in the case where there could be something or nothing, nothing is there.

(Haskell, by the way, calls that type Maybe, maybe that helps :slight_smile: )


#6

Many thanks for this! I am quite happy with these examples. Thanks for your great response @birkenfeld and @skade. This makes sense now.


#7

While this is visually evocative, I would resist using this metaphor, since “box” already means something in Rust.


#8

Yeah, hence the quotes. Any suggestions? “Burrito” maybe :slight_smile:


#9

Wrapper is perfectly fine and generic enough. Also fits the use of unwrap.


#10

Hmmm, what’s another kind of box… maybe a container of some sort? Maybe a "crate’? :stuck_out_tongue:

“wraps it up” evokes a package of some kind. I guess “container” kind of works…


#11

Oh oH!!! but crate has another meaning already too!! :slight_smile:


#12

if I wanted to make a vec of pointers to stucts that all have impl certain_trait in common is there a strait forward way to do this? I keep running into lifetime or type mismatch errors…seems strait forward enough…


#13

I actually just wrote out an example of this for someone on IRC:

http://is.gd/OpjkKv


#14

By the way: you only need to use “as” on the first element of the Vector, the second will be inferred.

http://is.gd/vi5DOZ


#15

That does look interesting! I will give it a shot after work tonight :slight_smile: