super is a fork / reimplementation of the glue package with a focus on efficiency and simplicity at a cost of flexibility.
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 <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 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.
library(super)
bar <- "baz"
glue("foo{bar}")
#> [1] "foobaz"
dat <- head(cbind(car = rownames(mtcars), mtcars))
glue("{car} does {mpg} mpg.", dat)
#> [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."          
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.
Over embraced arguments
head(glue("Item {LETTERS}"))
#> [1] "Item A" "Item B" "Item C" "Item D" "Item E" "Item F"
But not over input strings (yet)
glue(letters)
#> `x` must be a character vector of length <= 1.
library(microbenchmark)
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.782214  2.587956  2.197582  2.400856  2.214942  0.4580382   100
#>    super  9.072595  8.454834  7.399279  7.960057  7.165952  2.4771410   100
#>     glue 72.822142 66.567353 55.934250 60.870185 53.413350 23.1062460   100
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.659456  1.572940  1.586798  1.546465  1.484524  3.337508   100
#>    super  2.826638  2.656737  2.653470  2.668520  2.543139  3.301033   100
#>     glue 17.709209 16.457545 15.890143 15.975113 15.309042 15.412523   100
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 4.069276 3.966611 3.808481 3.859277 3.831744 1.549241   100
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.3168538 1.3193258 1.316968 1.319494 1.3007045 1.444807   100
#>   paste0 0.9935842 0.9997267 1.001962 1.014473 0.9986161 1.012222   100
#>    super 1.0000000 1.0000000 1.000000 1.000000 1.0000000 1.000000   100
#>     glue 1.1014867 1.1357466 1.140687 1.142420 1.1223596 1.202891   100