super

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

Examples

library(super)

Simple concatenation

bar <- "baz"
glue("foo{bar}")
#> [1] "foobaz"

list-like input

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

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

head(glue("Item {LETTERS}"))
#> [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

library(microbenchmark)

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.941176  2.638655  2.311134  2.321429  2.235294  0.5853018   100
#>    super  9.647059  8.781513  7.945124  7.628571  7.215686  7.3202100   100
#>     glue 77.019608 67.689076 58.144985 58.185714 54.104575 22.7874016   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.0000000   100
#>   paste0  1.650456  1.618497  1.513562  1.551213  1.536585 0.6293149   100
#>    super  2.762918  2.726879  2.618338  2.659030  2.620026 1.9612321   100
#>     glue 16.753799 16.417630 15.124414 15.576954 15.093710 6.6601699   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.00000 1.000000   100
#>   glue 4.018403 3.921805 3.742982 3.729639 3.71174 1.862811   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.1303083 1.1148474 1.1091331 1.107672 1.1090690 1.069603   100
#>   paste0 0.9926361 0.9981395 0.9983145 1.003376 0.9995117 1.002943   100
#>    super 1.0000000 1.0000000 1.0000000 1.000000 1.0000000 1.000000   100
#>     glue 1.1099883 1.1234326 1.1346951 1.114802 1.1283944 1.305985   100