--- title: "super" output: litedown::html_format: options: embed_resources: ["all"] vignette: > %\VignetteEngine{litedown::vignette} %\VignetteIndexEntry{super} %\VignetteEncoding{UTF-8} %\VignetteDepends{microbenchmark, glue} --- super is a fork / reimplementation of the [glue](https://glue.tidyverse.org) package with a focus on efficiency and simplicity at a cost of flexibility. As of the 0.0.1 release it should be considered 'experimental'. ## Differences from glue - `super::glue()` takes only two arguments: A character string that is used as a template and an environment to look up the embraced inputs. There is no option to change the delimiters from being a pair of braces (e.g. `{name}`). - Embraced inputs are always looked up in the provided environment (akin to calling `get()`) and are not evaluated. This is similar to `glue::glue_safe()` and `glue::glue_data_safe()` but note that this is not the default behaviour of `glue::glue()`. - `super::glue()` does not trim inputs. Instead this is done by either the function `super::glut()` or explicitly by `glue(trim(x))`. - `super::glue()` returns an unclassed character vector whereas `glue::glue()` returns a `` object and provides a variety of methods to work on that object. - At present, `super::glue()` does not provide any allowance for different handling of `NA` and `NULL` values, instead following the behaviour of `paste()`. - Recycling of embraced arguments currently follows standard R recycling rules where the arguments will be recycled to the length of the longest one. - `glue::glue()` arguments (and their associated behaviours) `.comment`, `.literal` and `.transformer` are not implemented. ## Examples ```{r} library(super) ``` ### Simple concatenation ```{r} bar <- "baz" glue("foo{bar}") ``` ### list-like input ```{r} dat <- head(cbind(car = rownames(mtcars), mtcars)) glue("{car} does {mpg} mpg.", dat) ``` ### Trimmed output ```{r} name <- "Fred" age <- 50 anniversary <- as.Date("1991-10-12") out <- glut(" My name is {name}, my age next year is {age}, my anniversary is {anniversary}. ") cat(out) ``` ### Partially vectorised Over embraced arguments ```{r} head(glue("Item {LETTERS}")) ``` But not over input strings (yet) ```{r} tryCatch( glue(letters), error = function(e) conditionMessage(e) ) ``` ## Relative timing benchmarks ```{r} library(microbenchmark) ``` ### Simple concatenation ```{r} #| print = xfun:::record_print.default bar <- "baz" bob <- 20 microbenchmark( sprintf = sprintf("foo%s %d", bar, bob), paste0 = paste0("foo", bar, " ", bob), super = super::glue("foo{bar} {bob}"), glue = as.character(glue::glue_safe("foo{bar} {bob}", .trim = FALSE)), unit = "relative", check = "identical" ) ``` ### Data frame input ```{r} #| print = xfun:::record_print.default dat <- head(cbind(car = rownames(mtcars), mtcars)) microbenchmark( sprintf = with(dat, sprintf("%s does %.3g mpg.", car, mpg)), paste0 = with(dat, paste(car, "does", mpg, "mpg.")), super = super::glue("{car} does {mpg} mpg.", dat), glue = as.character(glue::glue_data(dat, "{car} does {mpg} mpg.")), unit = "relative", check = "identical" ) ``` ### Trimmed output ```{r} #| print = xfun:::record_print.default microbenchmark( super = super::glut(" My name is {name}, my age next year is {age}, my anniversary is {anniversary}. "), glue = as.character(glue::glue(" My name is {name}, my age next year is {age}, my anniversary is {anniversary}. ")), unit = "relative", check = "identical" ) ``` ### Vectorized performance For larger input with both `glue::glue()` and `super::glue()`, the performance becomes dominated by the internally constructed call to `paste0()`, hence the convergence observed below. ```{r} #| print = xfun:::record_print.default bar <- rep("baz", 1e5) microbenchmark( sprintf = sprintf("foo%s %d", bar, bob), paste0 = paste0("foo", bar, " ", bob), super = super::glue("foo{bar} {bob}"), glue = as.character(glue::glue_safe("foo{bar} {bob}", .trim = FALSE)), unit = "relative", check = "identical" ) ```