Clojure is a modern Lisp dialect. Due to its Lisp/Scheme roots, R is somewhat similar (functional programming with immutable data; macros a.k.a. non-standard evaluation a.k.a. code as data a.k.a. homoiconicity), but lacks some useful and terse language constructs. This is an attempt to implement them in R.
The implemented functions (macros):
cond
and related -- see https://clojuredocs.org/clojure.core/condcase
and related -- see https://clojuredocs.org/clojure.core/caseas->
-- see https://clojuredocs.org/clojure.core/as-%3E->
-- see https://clojuredocs.org/clojure.core/-%3E->>
-- see https://clojuredocs.org/clojure.core/-%3E%3Econd->
and related -- generalised version inspired by https://clojuredocs.org/clojure.core/cond-%3Edoc
-- see https://clojuredocs.org/clojure.repl/docNew functions (macros) may be added gradually in the future.
devtools::install_github('alekrutkowski/clojR')
library(clojR)
cond
and related# Also vectorised `condv` is available (based on base::ifelse). # Example based on the first example from # https://clojuredocs.org/clojure.core/cond # Transformed to: # if (n < 0) "negative" else if (n > 0) "positive" else "zero" `pos-neg-or-zero` <- function(n) cond(n < 0, 'negative', n > 0, 'positive', 'zero') `pos-neg-or-zero`(5) `pos-neg-or-zero`(-1) `pos-neg-or-zero`(0) # condv(n < 0, 'negative', # n > 0, 'positive', # 'zero') # would transform to: # ifelse(n < 0, "negative", ifelse(n > 0, "positive", "zero"))
case
and related# More powerful than base::switch # not only letters or integers can be used as keys: f <- base::mean case(f, stats::median, 1, base::mean, 2, 3) # Different vectorised variants of case # (using `ifelse` instead of `if` under the hood): x <- c(1/0, as.numeric(NA), NaN, 0) # `casevid` # based on vectorised base::identical casevid(x, Inf, "infinity", as.numeric(NA), "not available", "other") # `caseveq` # based on `==` (equality) # less general than `casevid` but likely faster caseveq(x, Inf, "infinity", as.numeric(NA), "not available", "other")
# Possible alternatives to pipe operators # like %>% in package `magrittr` # `Thread-first` -- transformed to: # sum(3 - 400, 7, 8) `->`(3, `-`(400), sum(7,8)) # `Thread-last` -- transformed to: # sum(7, 8, 400 - 3) `->>`(3, `-`(400), sum(7,8)) # `Thread-as` -- transformed to: # sum(c(mean(c(1, 1000)), 5)) - 13 `as->`(1000, nn, mean(c(1,nn)), sum(c(nn,5)), `-`(nn,13))
# Slightly modified (generalised) compared to the Clojure version as it is threading the # a value not only through the right-side expresions but also through # the conditions/tests (while in Clojure these are static conditions): `cond->`(1, # we start with 1 `==`(1), `+`(1), # 1==1 is true so 1+1 is evaluated and yields 2 which is threded further `<`(0), `*`(42), # 2<0 is false so the operation is skipped `==`(2), `*`(3)) # 2==2 is true so 2*3 is evaluated and it finally yields 6 # A version closer in spirit to the Clojure example -- the constants need to be wrapped # in anonymous functions or in a function which ignores its first argument # (see `constant` below): `cond->`(1, # we start with 1 function(x) TRUE, `+`(1), # the condition is true so 1+1 yields 2 function(x) FALSE, `*`(42), # the condition is false so the operation is skipped function(x) 2==2, `*`(3)) # 2==2 so it yields 6 constant <- function(ignore_me, v) v `cond->`(1, # we start with 1 constant(TRUE), `+`(1), # the condition is true so 1+1 yields 2 constant(FALSE), `*`(42), # the condition is false so the operation is skipped constant(2==2), `*`(3)) # 2==2 so it yields 6 # Use inside a function: zz <- function(v,n) `cond->`(v, constant(n>1), `+`(1), constant(n>2), `+`(2), constant(n>3), `+`(3)) zz(10, 2.5) # Also a vectorised version `condv->` using internally `ifelse` rather than `if` # is available.
# Extraction of inline "docstrings": # an informal documentation, e.g. for # functions not in a package. # Use the double hash character (##) # for the comments to be detected by `doc`. fff <- function(x = 1) { ## This is my function: ## argument x, default 1. ## returns x + 10. x + 10 } doc(fff)
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.