#[derive(Default)]
struct Foo {
…
}
struct Bar {
…
}
fn do_something(foo: Foo) -> Bar {
# do something with Foo and return a Bar
…
}
fn main() {
let opt_foo: Option<Foo> = None;
// panics
let foo: Foo = opt_foo.unwrap();
// panics, but with an error message of your choosing
let foo: Foo = opt_foo.expect("foo was supposed to be there");
// converts the Option (Some or None) to a Result (Ok or Err,
// where Err can contain an error type or message and then passed
// around or returned or whatever)
let foo: Result<Foo> = opt_foo.ok_or("foo was supposed to be there");
// replaces it with a value of your choosing if it's not there
let foo: Foo = opt_foo.unwrap_or(Foo { … });
// replaces it with the default value the type defines
let foo: Foo = opt_foo.unwrap_or_default();
// keeps it as `None`, or if it's actually something then
// replaces the internal contents with the result of the
// function call
let bar: Option<Bar> = opt_foo.map(do_something);
// does arbitrary logic in the match arm if foo is there
match opt_foo {
Some(foo) => { do something with foo },
None => { do something else },
}
}
There are a few dozen other things you can do with an Option that handle the rarer use-cases, but the above are like 95%+ of what you want.
You're explicitly choosing to panic if it is None. Would never pass a code review unless you can in very clear terms tell why it will never now or in the future be none.
The point is that you can't use the inner value without choosing a course of action if it happens to be none.
The comment that you -- with aloof disbelief -- replied to only talked about pointers. I don't know what point you think you are proving with these pithy replies. It sure does go above my head. :)
Well, this is a thread about storing sql null. I'm trying to suss out how sane languages represent sql null in a way that can't go wrong. So far the answers mostly seem to be use a type that can't represent sql null or use a type that explodes when you use it wrong. With a side of real programmers don't let bugs pass code review.
With all due respect, it appears as if you have entered this conversation with this belief and have used that perspective as a filter when other commenters have tried to correct that perspective.
It may be surprising to learn that languages without implicitly-nullable types are real, but you should understand that none of these people would be trying to tell you about this if these languages simply exploded any time you used them the wrong way.
> I'm trying to [sass] out how sane languages represent sql null in a way that can't go wrong.
There is a difference between a type Pointer where `null` is an instance of that type and a type Box which only has valid (can be dereferenced) values. If the language has e.g. algebraic data types and pattern matching then Option(al)<Box> can be safely matched on and Box can be used in the branch (the pattern match arm) where Some(Box). Meanwhile in a language with Pointer and no flow analysis any dereference of Pointer could lead to some kind of "panic".
Say "unwrap()" all you want but the two approaches are clearly very different.
Where did anyone anywhere in this thread claim that you could "represent sql null in a way that can't go wrong?"
Yes, Rust options explode if you unwrap a None. But that's explicitly what `unwrap()` does. It a big improvement over any random access potentially implicitly exploding.
It seems like sql types that include null and non-null values are a union of at least two different types. In general, if you write code to handle a tagged union that has "panic!" in one of the prongs, you'll get panics. Don't do that?
The quote is talking about plain pointers being dangerous.
And in turn, the claim above was that some languages have plain pointers that aren't dangerous.
Yes, you can put a pointer into an Option that can fail, but that's a different issue. The point is that "can fail" is not built directly into the pointer type, and you can use pointers that don't have that risk.
And to be clear, that claim is not directly addressing the issue of SQL null. It's a baseline discussion of what pointers actually imply by nature of being pointers. We can then better build upon that knowledge after we separate "refers to a data location" and "might not have contents" into separate attributes.