Skip to content

Instantly share code, notes, and snippets.

@lionel-
lionel- / tidyverse-c-api-compat.md
Last active July 15, 2024 13:09
Compatibility of tidyverse with the public C API of R

Summary of meeting between Tidyverse members and Luke Tierney at useR! 2024.

Frame/Environment inspection

Frontends and low level tools need to know what kind of bindings they are dealing with. Objectives include:

  • Avoiding side effects such as triggering a promise or causing a missing argument error. Low level tools often can't afford to protect against those for every variable lookup. Figuring out what happened by inspecting errors is also ambiguous, and sometimes impossible (promises may cause longjumps in a variety of ways).

  • Transparency in debugging/development settings. Providing context to the user about what's going to happen if they attempt to retrieve the value of a binding (i.e. an active binding invokation, a promise forcing leading to the evaluation of such and such expression, etc).

Homebrew build logs for [email protected] on macOS 13
Build date: 2023-04-02 14:50:46
Homebrew build logs for [email protected] on macOS 13
Build date: 2023-04-02 14:50:46
@lionel-
lionel- / source-unwind.R
Last active February 24, 2022 16:00
Unwinding scope in `source()`
# Prototype of `source()` as currently implemented
source2 <- function(file, env = parent.frame()) {
exprs <- parse(file)
for (expr in exprs) {
eval(expr, env)
}
}
# Prototype of `source()` using an evaluation strategy where the
# unwinding scope is the whole file rather than each line
makeDelayedBinding <- function(sym,
expr,
eval.env = parent.frame(1),
assign.env = parent.frame(1)) {
expr <- substitute(expr)
value <- NULL
forced <- FALSE
forceDelayed <- function() {
@lionel-
lionel- / recode.R
Created July 22, 2019 12:30
Recoding values
# The general idea is to supply a recoding specification through a
# data frame of keys and values. They keys are a generalisation of
# names, they can be any type.
keys <- function(key, value) {
tibble::tibble(.key = key, .value = value)
}
dribbleys <- function(...) {
tibble::tribble(~ .key, ~ .value, ...)
@lionel-
lionel- / wrapping-dt.R
Created June 25, 2019 10:54
Wrapping DT
# Simple DT wrapper
summarise <- function(data, j, by) {
data <- data.table::as.data.table(data)
data[
i = ,
j = eval(substitute(j)),
by = eval(substitute(by))
]
}
@lionel-
lionel- / starts-with.R
Created April 9, 2019 08:31
Does a vector start with the same values as another vector
truncate_len <- function(x, n) {
if (length(x) < n) {
stop("Can't truncate vector to the given length because it is already shorter")
}
x[seq_len(n)]
}
truncate_along <- function(x, y) {
truncate_len(x, length(y))
@lionel-
lionel- / magrittr-tidy-eval.R
Last active December 17, 2017 10:19
Unquoting RHS of magrittr pipe with quosure support
# Actually does not work because quosured magrittr pronouns are not
# evaluated in the right environment
library("magrittr")
library("rlang")
# Anticipate renaming of `quo_is_lang()` in rlang
quo_is_call <- quo_is_lang
@lionel-
lionel- / depend.R
Last active December 2, 2017 14:01
Handle hard dependencies in library()
depend <- function(..., character.only = FALSE) {
# Mimic library()'s UI
if (character.only) {
packages <- c(...)
} else {
packages <- substitute(c(...))[-1]
if (!all(vapply(packages, is.symbol, logical(1)))) {
stop("Can't supply expressions if `character.only` is FALSE")
}