R package for falsy and truthy values
R Makefile
Switch branches/tags
Nothing to show
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Failed to load latest commit information.
R
man
tests
vignettes
.Rbuildignore
.travis.yml
DESCRIPTION
LICENSE
Makefile
NAMESPACE
README.md
appveyor.yml

README.md

falsy

Linux Build Status Windows Build status CRAN RStudio mirror downloads

falsy defines falsy and truthy values. You might be familiar with them in other dynamic laguanges with prevalent implicit type conversions, e.g Python, Ruby, JavaScript and Lisp.

These languages typically define a set of values that are considered as false when used as a condition, and everything else is considered as true. The falsy package does the same for R.

The following R values are considered to be falsy:

  • NULL
  • FALSE
  • 0L, the integer zero value.
  • 0, the real zero value.
  • 0+0i, the complex zero value.
  • "" empty string character scalar.
  • 00 one byte raw vector with zero value.
  • Empty vectors: logical(), integer(), double(), complex(), character() and raw().
  • Empty lists: list().
  • Objects from the try-error class.

Note that the value must be completely identical to one of the listed ones to be falsy. E.g. an empty vector with an attribute is not falsy any more.

Everything else is truthy. In particular, everything with a class attribute is truthy. So empty vectors are falsy, but empty matrices are truthy.

Functions

The is_falsy and is_truthy functions simply decide if a value is falsy or truthy.

library(falsy)
is_falsy(0)
## [1] TRUE
is_falsy(list())
## [1] TRUE
is_falsy("")
## [1] TRUE
is_truthy(0)
## [1] FALSE
is_truthy("0")
## [1] TRUE
is_truthy(matrix(nrow=0, ncol=0))
## [1] TRUE

Robust short-circuited logical operators

It is common to use truthy and falsy values with the short-circuited logical and and or operators, becuase the code will be short and (usually) readable. E.g. one can check if a vector has elements or give an error message:

v <- 1:5
length(v) > 0 || stop("empty v")
## [1] TRUE
v <- c()
length(v) > 0 || stop("empty v")
## Error in eval(expr, envir, enclos): empty v

Unfortunately, the || and && operators fail on values that cannot be converted to a logical, using a (non-extendable) set of implicit conversion rules. The falsy package privides the %||% and %&&% operators that are essentially identical to || and &&, but work with truthy and falsy values. This allows writing:

v <- 1:5
v %||% stop("empty v")
## [1] 1 2 3 4 5
v <- c()
v %||% stop("empty v")
## Error in eval(rhs, envir = parent.frame()): empty v

and more importantly also

l <- list(a = 1, b = 2)
l$a %||% stop("no a in l")
## [1] 1
l$c %||% stop("no c in l")
## Error in eval(rhs, envir = parent.frame()): no c in l

This works, because for non-existing keys lists return NULL, which is falsy.

The left or right hand sides of the %||% and %&&% operators can be arbitrary R expessions. E.g. to shift a vector to zero, if it is not empty, one can write

v <- 5:10
v %&&% { v <- v - min(v) }
## [1] 0 1 2 3 4 5
v
## [1] 0 1 2 3 4 5
v <- numeric()
v %&&% { v <- v - min(v) }
## numeric(0)

which is somewhat simpler than writing

if (length(v) > 0) v <- v - min(v)

Errors and try

Errors returned by try are also falsy, which helps writing fallback solutions.

col <- try(colorspace::rainbow_hcl(5)) %||% rainbow(5)
col
## [1] "#E495A5" "#BDAB66" "#65BC8C" "#55B8D0" "#C29DDE"

You probably want to suppress the misleading error message, whith is possible with try_quietly:

col2 <- try_quietly(colorspace::rainbow_hcl(5)) %||% rainbow(5)
col2
## [1] "#E495A5" "#BDAB66" "#65BC8C" "#55B8D0" "#C29DDE"

Negation

The nay function returns a falsy value if its argument is truthy and vice versa. The following code checks if a directory is empty:

dir.create(tmp <- tempfile())
nay(dir(tmp, all.files = TRUE, no.. = TRUE)) %||% message("Not empty")
## [1] TRUE
cat("Hello!", file = file.path(tmp, "foo"))
nay(dir(tmp, all.files = TRUE, no.. = TRUE)) %||% message("Not empty")
## Not empty
## NULL

Working with magrittr pipes

falsy goes well with the pipe operator of the magrittr package. In particular, a falsy or truthy value in pipe can be replaced with another value using %||% and %&&%:

library(magrittr)
vect <- 1:10
vect %>%
  sum() %||% "foo" %>%
  paste("!!!")
## [1] "55 !!!"
vect <- c()
vect %>%
  sum() %||% "foo" %>%
  paste("!!!")
## [1] "foo !!!"

Warnings

FALSE and falsy are not the same

From the definition of falsy values, it might not be obvious, but there are some values that R considers true, are falsy, and some values that R considers false are truthy.

The most notable example is objects with attributes. R does not care about the presense of attributes in the condition of the if construct, but falsy does:

obj <- matrix(FALSE, 1, 1)
if (!obj) "false"
## [1] "false"
is_falsy(obj)
## [1] FALSE

Vectors

falsy behaves somewhat surprisingly with vectors. Empty vectors are falsy, but some of the non-empty ones are truthy, the most obvious example beging FALSE, which is also a length one logical vector. The others are 0, 0L, "", 0+0i and as.raw(0). (See at the beginning.) This means that you cannot reliably use %||% to check if a vector is empty. You need to check the legth of the vector explicitly.

empty <- c()
non_empty1 <- c("foo", "bar")
non_empty2 <- c("")
is_falsy(empty)
## [1] TRUE
is_falsy(non_empty1)
## [1] FALSE
is_falsy(non_empty2)
## [1] TRUE

This is incorrect:

non_empty2 %||% stop("empty vector!")
## Error in eval(rhs, envir = parent.frame()): empty vector!

The correct way to test if a vector is empty is to test if its length is zero:

length(non_empty2) %||% stop("empty vector!")
## [1] 1