From 8273e021db676f9ccfab13057f45b76cf4302d9c Mon Sep 17 00:00:00 2001 From: spaceface777 Date: Sun, 12 Jul 2020 19:27:41 +0200 Subject: [PATCH] doc: clarify that an `or` block may end with a default value (#5814) --- doc/docs.md | 42 ++++++++++++++++++++++++++++++++---------- 1 file changed, 32 insertions(+), 10 deletions(-) diff --git a/doc/docs.md b/doc/docs.md index 51bdd0733c..f0f0e3ce3f 100644 --- a/doc/docs.md +++ b/doc/docs.md @@ -1373,14 +1373,8 @@ fn (r Repo) find_user_by_id(id int) ?User { fn main() { repo := new_repo() - user := repo.find_user_by_id(10) or { - // Option types must be handled by `or` blocks. - // Any `or` block, *must* end with one of: - // a) `break`, `continue` or `return` . - // b) a panic("message") or exit(code) call . - // c) a default value of the same type as the Option . - // (i.e. if the function returns for example ?int, you may put 1234 as default value) - return + user := repo.find_user_by_id(10) or { // Option types must be handled by `or` blocks + return } println(user.id) // "10" println(user.name) // "Charles" @@ -1408,7 +1402,9 @@ user := repo.find_user_by_id(7) or { } ``` -You can also propagate errors: +There are three ways of handling an optional. + +The first method is to propagate the error: ```v resp := http.get(url)? @@ -1416,7 +1412,8 @@ println(resp.text) ``` `http.get` returns `?http.Response`. Because it was called with `?`, the error will be propagated to the calling function -(which must return an optional). If it is used in the `main()` function it will cause a panic. +(which must return an optional as well). If it is used in the `main()` function it will `panic` instead, since the error +cannot be propagated any further. The code above is essentially a condensed version of @@ -1427,6 +1424,31 @@ resp := http.get(url) or { println(resp.text) ``` +The second is to break from execution early: + +```v +user := repo.find_user_by_id(7) or { + return +} +``` + +Here, you can either call `panic()` or `exit()`, which will stop the execution of the entire program, +or use a control flow statement (`return`, `break`, `continue`, etc) to break from the current block. +Note that `break` and `continue` can only be used inside a `for` loop. + +The third method is to provide a default value at the end of the `or` block. In case of an error, +that value would be assigned instead, so it must have the same type as the `Option` being handled. + +```v +fn do_something(s string) ?string { + if s == 'foo' { return 'foo' } + return error('invalid string') // Could be `return none` as well +} + +a := do_something('foo') or { 'default' } // a will be 'foo' +b := do_something('bar') or { 'default' } // b will be 'default' +``` + V does not have a way to forcibly "unwrap" an optional (as other languages do, for instance Rust's `unwrap()` or Swift's `!`). To do this use `or { panic(err) }` instead.