---
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")
)
```

