knitr::opts_chunk$set( collapse = TRUE, comment = "#>", fig.path = "README-" )
match_with() simulates pattern matching that is used in many functional programming language such as 'case of' in Haskell and 'match with' in OCaml.
# install.packages("devtools") devtools::install_github("tobcap/matchwith") library("matchwith")
library(matchwith)
# Syntax f <- function(expr) { match_with(expr , pattern_1 -> res_1 , pattern_2 -> res_2 ... , pattern_n -> res_n ) }
pattern_i
represents numeric literal, charater literal, or NULL.
When x is matched with pattern_i
, res_i
(the right side of expression) is evalueted in the parent.frame .
In the exampe below, when x is 0 or 1, the right side expression is evalated
and returned. when x is more than 1, wildcard simbol is matched and
fib(x-1) + fib(x-2)
is evaluated and returned.
fib <- function(x) match_with(x , 0 -> 0 , 1 -> 1 , . -> fib(x - 1) + fib(x - 2) ) fib(10)
::
is used for DSL porpose that is representing constructor of head and tail.
when pattern is y::ys
, the first object of x
is assigned to y
and rest
of that is assigned to ys
.
sum1 <- function(x) match_with(x , integer(0) -> 0L , y::ys -> y + sum1(ys) ) sum1(1:5)
sum2 <- function(x, acc = 0L) match_with(x , integer(0) -> acc , y::ys -> sum2(ys, acc + y) ) sum2(1:5)
When pattern_i
starts with list
and includes new symbols as
list's arguments, the coresponding values of x
which must have
the same language structure will be assigned to the new symbols,
and res_i
is evaluated with using such symbol-value-associated-list.
ex1 <- function(x) match_with(x , list(a, b) -> 10 * a + b , list(a, b, c) -> 100 * a + 10 * b + c , . -> x ) ex1(list(1,2)) ex1(list(1,2,3)) str(ex1(list(1,2,3,4)))
Wildcard inside list
of pattern_i
can be used.
fizzbuzz1 <- function(x) match_with(list(x %% 3, x %% 5) , list(0, 0) -> "fizzbuzz" , list(0, .) -> "fizz" , list(., 0) -> "buzz" , . -> as.character(x) ) sapply(1:30, fizzbuzz1)
Other than list
, x
is compared with pattern_i
and if it matches, res_i
is evaluated.
ex2 <- function(x) match_with(x , 1:3 -> 2 * x , 1:5 -> 3 * x , . -> 100 * x ) ex2(1:3) ex2(1:5) ex2(1:4) ex2(c(1,2,3)) # 1:3 is integer class, c(1,2,3) is numeric class ex2(c(1L,2L,3L))
when pattern_i
uses Compare
family (r getGroupMembers("Compare")
)
(or !
, any
, all
, identity
, isTRUE
) or a function whose name
starts with is.
as a top node of language object, it is regarded as
guard clauses, and when the result of evaluating pattern_i
is TRUE,
res_i
will be evaluated and returned.
Note that r getGroupMembers("Logic")
possibly return vector of
boolean object whose length may have more than 2, so all() or any() is
required to use them.
ex3 <- function(x) match_with(x , x > 5 -> x * 100 , x < 3 -> x * 10 , . -> -x ) sapply(1:10, ex3) # thanks to @Keiku issue#1 ex4 <- function(x) match_with(x , all(1 <= x & x <= 10) -> "1-10" , all(11 <= x) -> "11+" , otherwise -> "other" ) ex4(1:10) ex4(8:12) ex4(11:14) ex4(5) ex4(15) ex4(-1)
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.