Define Truthy and Falsy Values

A value is falsy if it is NULL, FALSE, the empty string, zero, or an empty vector or list. Other values are truthy. The new %&&% and %||% operators work with falsy and truthy values and can be used for concise conditional execution.


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.

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

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: 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: 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: 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 returned by try are also falsy, which helps writing fallback solutions.

col <- try(colorspace::rainbow_hcl(5)) %||% rainbow(5)
col
## [1] "#FF0000FF" "#CCFF00FF" "#00FF66FF" "#0066FFFF" "#CC00FFFF"

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] "#FF0000FF" "#CCFF00FF" "#00FF66FF" "#0066FFFF" "#CC00FFFF"

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

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 !!!"

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

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: 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

News

Reference manual

It appears you don't have a PDF plugin for this browser. You can click here to download the reference manual.

install.packages("falsy")

1.0.1 by Gabor Csardi, 2 years ago


https://github.com/gaborcsardi/falsy


Report a bug at https://github.com/gaborcsardi/falsy/issues


Browse source code at https://github.com/cran/falsy


Authors: Gabor Csardi [aut, cre]


Documentation:   PDF Manual  


MIT + file LICENSE license


Suggests testthat


See at CRAN