From 2c9e890c3d9fa65b2a9b46317492d5e20d745eae Mon Sep 17 00:00:00 2001 From: Alexander Medvednikov Date: Mon, 24 Oct 2022 16:11:20 +0300 Subject: [PATCH] doc: document the Option/Result split --- doc/docs.md | 37 ++++++++++++++++++++++++++----------- 1 file changed, 26 insertions(+), 11 deletions(-) diff --git a/doc/docs.md b/doc/docs.md index 2c25996852..072847f5ea 100644 --- a/doc/docs.md +++ b/doc/docs.md @@ -3502,7 +3502,12 @@ This is a special case of a [sum type](#sum-types) declaration. ### Option/Result types and error handling -Option types are declared with `?Type`: +Optional types are for types which may represent `none`. Result types may represent an error returned from a function. + +`Option` types are declared by prepending `?` to the type name: `?Type`. +`Result` types use `!`: `!Type`. + + ```v struct User { id int @@ -3513,42 +3518,52 @@ struct Repo { users []User } -fn (r Repo) find_user_by_id(id int) ?User { +fn (r Repo) find_user_by_id(id int) !User { for user in r.users { if user.id == id { - // V automatically wraps this into an option type + // V automatically wraps this into a result or option type return user } } return error('User $id not found') } +// A version of the function using an optional +fn (r Repo) find_user_by_id2(id int) ?User { + for user in r.users { + if user.id == id { + return user + } + } + return none +} + fn main() { repo := Repo{ users: [User{1, 'Andrew'}, User{2, 'Bob'}, User{10, 'Charles'}] } - user := repo.find_user_by_id(10) or { // Option types must be handled by `or` blocks + user := repo.find_user_by_id(10) or { // Option/Result types must be handled by `or` blocks + println(err) return } println(user.id) // "10" println(user.name) // "Charles" + + user2 := repo.find_user_by_id2(10) or { return } } ``` -V combines `Option` and `Result` into one type, so you don't need to decide which one to use. +V used to combine `Option` and `Result` into one type, now they are separate. -The amount of work required to "upgrade" a function to an optional function is minimal; -you have to add a `?` to the return type and return an error when something goes wrong. - -If you don't need to return an error message, you can simply `return none` -(this is a more efficient equivalent of `return error("")`). +The amount of work required to "upgrade" a function to an optional/result function is minimal; +you have to add a `?` or `!` to the return type and return an error when something goes wrong. This is the primary mechanism for error handling in V. They are still values, like in Go, but the advantage is that errors can't be unhandled, and handling them is a lot less verbose. Unlike other languages, V does not handle exceptions with `throw/try/catch` blocks. `err` is defined inside an `or` block and is set to the string message passed -to the `error()` function. `err` is empty if `none` was returned. +to the `error()` function. ```v oksyntax user := repo.find_user_by_id(7) or {