super is a fork / reimplementation of the glue 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 toglue::glue_safe()
andglue::glue_data_safe()
but note that this is not the default behaviour ofglue::glue()
.super::glue()
does not trim inputs. Instead this is done by either the functionsuper::glut()
or explicitly byglue(trim(x))
.super::glue()
returns an unclassed character vector whereasglue::glue()
returns a<glue>
object and provides a variety of methods to work on that object.At present,
super::glue()
does not provide any allowance for different handling ofNA
andNULL
values, instead following the behaviour ofpaste()
.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
list-like input
## [1] "Mazda RX4 does 21 mpg." "Mazda RX4 Wag does 21 mpg."
## [3] "Datsun 710 does 22.8 mpg." "Hornet 4 Drive does 21.4 mpg."
## [5] "Hornet Sportabout does 18.7 mpg." "Valiant does 18.1 mpg."
Trimmed output
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)
## My name is Fred,
## my age next year is 50,
## my anniversary is 1991-10-12.
Partially vectorised
Over embraced arguments
## [1] "Item A" "Item B" "Item C" "Item D" "Item E" "Item F"
But not over input strings (yet)
tryCatch(
glue(letters),
error = function(e) conditionMessage(e)
)
## [1] "`x` must be a character vector of length <= 1."
Relative timing benchmarks
Simple concatenation
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"
)
## Unit: relative
## expr min lq mean median uq max neval
## sprintf 1.000000 1.000000 1.000000 1.000000 1.000000 1.0000000 100
## paste0 2.628975 2.417261 1.691085 1.660777 1.680842 0.2319008 100
## super 9.212898 8.263039 6.160767 6.311100 5.606316 3.5426248 100
## glue 81.193463 70.585741 46.695115 47.335739 40.842526 12.5723968 100
Data frame input
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"
)
## Unit: relative
## expr min lq mean median uq max neval
## sprintf 1.000000 1.000000 1.000000 1.000000 1.000000 1.000000 100
## paste0 1.652230 1.576810 1.473244 1.483684 1.393527 2.010994 100
## super 2.877958 2.807014 2.568070 2.801890 2.481449 1.338481 100
## glue 19.464076 18.265600 16.071341 16.656581 14.711170 9.645303 100
Trimmed output
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"
)
## Unit: relative
## expr min lq mean median uq max neval
## super 1.000000 1.000000 1.000000 1.000000 1.000000 1.000000 100
## glue 3.839726 3.726157 3.576701 3.618956 3.569012 1.805505 100
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.
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"
)
## Unit: relative
## expr min lq mean median uq max neval
## sprintf 1.524147 1.5097542 1.494169 1.469748 1.479917 1.418028 100
## paste0 1.000000 1.0000000 1.000000 1.000000 1.000000 1.000000 100
## super 1.011280 0.9999359 1.005869 1.001659 1.003474 1.042515 100
## glue 1.068944 1.0600638 1.063230 1.050927 1.043550 1.062091 100