--- title: "User Guide" author: "Antoine Champion" date: "`r Sys.Date()`" output: rmarkdown::html_vignette vignette: > %\VignetteIndexEntry{User Guide} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} %\VignetteDepends{magrittr} --- ```{r include = FALSE} library(optional) ``` ## Introduction ## This package adds an `optional` type, similar to `Option` in F#, OCaml and Scala, to `Maybe` in Haskell, and to nullable types in `C#`. It should be used instead of `NULL` for values that might be missing or otherwise invalid. This package also introduces pattern matching. ## Using the optional type ## `option` is an object wrapper which indicates whether the object is valid or not. ### Declaring an optional object ### An optional variable can be set to `option(object)` or to `none`. ```{r} a <- option(5) class(a) ``` Operators and print will have the same behavior with an `optional` than with its base type. ```{r} a == 5 a ``` Note that `option(option(obj))` equals `option(obj)` and that `option(none)` equals `FALSE`. To check whether an `optional` object is set to a value or to `none`, one can use the function `some()`. ```{r} a <- option(5) some(a) a <- none some(a) ``` ### Optionals on functions ### Given a function `f()`, to handle properly `optional` arguments and wraps its return type into an `optional`, one should use `make_opt()` the following way: ``` f_opt <- make_opt(f) ``` 1. Every `optional` argument passed to `f_opt()` will be converted to its original type before being sent to `f()`. If one or more of them is `none`, several behaviors are available (see `?make_opt`). 2. If `f()` returns null, or if an error is thrown during its execution, then `f_opt()` returns `none`. Else it will return `optional(f(...))`. For instance: ```{r} c_opt <- make_opt(c) c_opt(option(2), none, option(5)) c_opt() ``` ## Pattern matching ## Patterns are used in many functional languages in order to process variables in an exhaustive way. The syntax is the following: ``` match_with( variable, pattern , result-function, ... ``` If `variable` matches a `pattern`, `result-function` is called. For comparing optional types, it is a better habit to use `match_with()` rather than a conditional statement. ```{r} library(magrittr) a <- 5 match_with(a, . %>% option(.), paste, none, function() "Error!" ) ``` 1. Each `pattern` can be either: * an object or a primitive type (direct comparison with `variable`), * a list (match if `variable` is in the list), * a `magrittr` functional sequence that matches if it returns `variable`. The dot `.` denotes the variable to be matched. 2. If `result-function` takes no arguments, it will be called as is. Else, the only argument that will be sent is `variable`. You can also use the fallthrough function `fallthrough()` to permit the matching to continue even if the current pattern is matched. ```{r} a <- 4 match_with(a, 1, function() "Matched exact value", list(2, 3, 4), fallthrough(function() "Matched in list"), . %>% if (. > 3)., function(x) paste0("Matched in condition: ",x,">3") ) ```