Skip to content

Instantly share code, notes, and snippets.

@alekrutkowski
Last active June 10, 2016 09:31
Show Gist options
  • Save alekrutkowski/d654699f8992b446fe11ee149e59c625 to your computer and use it in GitHub Desktop.
Save alekrutkowski/d654699f8992b446fe11ee149e59c625 to your computer and use it in GitHub Desktop.
Clojure-style cond macro in R
library(magrittr)
cond <- function(...) {
# Clojure-style cond macro in R -- creates nested if-else calls
# arguments: pairs -- condition1, what-if-true1,
# condition2, what-if-true2,
# etc...
# what-if-all-contitions-false
e <- parent.frame()
substitute(list(...)) %>%
as.list %T>%
{if (length(.) < 4)
stop('\ncond requires at least 3 arguments!',
call.=FALSE)} %>%
tail(-1) %T>%
{if (length(.) %% 2 != 1)
stop('\ncond requires an uneven number of arguments!',
call.=FALSE)} %>%
split(((seq_along(.) + 1)/2) %>%
floor) %>%
rev %>%
{c(.[[1]], tail(., -1))} %>%
Reduce(function(x,y)
list(`if`, y[[1]], y[[2]], x) %>%
as.call, .) %>%
eval(envir=e)
}
# Example based on the first example from
# https://clojuredocs.org/clojure.core/cond
#
# `pos-neg-or-zero` <- function(n)
# cond(n < 0, 'negative',
# n > 0, 'positive',
# 'zero')
# `pos-neg-or-zero`(5)
# => "positive"
# `pos-neg-or-zero`(-1)
# => "negative"
# `pos-neg-or-zero`(0)
# => "zero"
condv <- function(...) {
# Clojure-style cond macro in R -- creates nested if-else calls
# A vectorised version using R's ifelse function rather than if
# arguments: pairs -- condition1, what-if-true1,
# condition2, what-if-true2,
# etc...
# what-if-all-contitions-false
e <- parent.frame()
substitute(list(...)) %>%
as.list %T>%
{if (length(.) < 4)
stop('\ncondv requires at least 3 arguments!',
call.=FALSE)} %>%
tail(-1) %T>%
{if (length(.) %% 2 != 1)
stop('\ncondv requires an uneven number of arguments!',
call.=FALSE)} %>%
split(((seq_along(.) + 1)/2) %>%
floor) %>%
rev %>%
{c(.[[1]], tail(., -1))} %>%
Reduce(function(x,y)
list(quote(ifelse), y[[1]], y[[2]], x) %>%
as.call, .) %>%
eval(envir=e)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment