tidyverse / glue Goto Github PK
View Code? Open in Web Editor NEWGlue strings to data in R. Small, fast, dependency free interpreted string literals.
Home Page: https://glue.tidyverse.org
License: Other
Glue strings to data in R. Small, fast, dependency free interpreted string literals.
Home Page: https://glue.tidyverse.org
License: Other
First of all, thanks for this great package! I'm migrating some of my internal R pkg functions from sprintf
, but found some scoping issues and decided to ask for some help here. I'm pretty sure it's not glue
related, rather just PEBKAC on my end, but cannot figure out what's the problem.
Example code:
lapply(1:2, function(x) glue::glue('{x * 2}'))
#> [[1]]
#> 2
#>
#> [[2]]
#> 4
Trying to use this with a helper function:
f <- function(msg) {
glue::glue(msg)
}
lapply(1:2, function(x) f('{x * 2}'))
#> Error in eval(x, envir = envir): object 'x' not found
Then trying to specify the parent frame:
f <- function(msg) {
glue::glue(msg, .envir = parent.frame())
}
lapply(1:2, function(x) f('{x * 2}'))
#> Error in eval(x, envir = envir): object 'msg' not found
So now it's evaluated in the parent frame, but looking for msg
instead of x
defined withing msg
.
I tried a couple of other things eg
f <- function(msg) {
eval.parent(glue::glue(msg))
}
lapply(1:2, function(x) f('{x * 2}'))
#> Error in eval(x, envir = envir): object 'x' not found
But did not figure this out. Any suggestions?
So you can do:
collapse(1:4, ",", last = ", and ")
#> 1, 2, 3, and 4
unglue()
so you could see the generalized form of whatever specific string that was made with glue()
.
Simple form would be something like:
library(glue)
unglue <- function(x) {
stopifnot(inherits(x, "glue"))
attr(x, "glue_string")
}
glue_string <- "echo '{saywhat}'"
x <- glue(glue_string, saywhat = "hello world")
attr(x, "glue_string") <- glue_string
str(x)
#> Class 'glue' atomic [1:1] echo 'hello world'
#> ..- attr(*, "glue_string")= chr "echo '{saywhat}'"
x
#> echo 'hello world'
unglue(x)
#> [1] "echo '{saywhat}'"
Ambitious form would also extract out the value of the inputs
unglue_ambitious(x)
#> [1] "echo '{saywhat}'"
#> ..- attr(*, "saywhat")= chr "hello world"
Sometimes you have the values that you want to interpolate in a list (example: the params
object in an Rmarkdown file), and you want to interpolate using these values. Currently, you must manually convert this to an environment in order to do so using glue, but it would be nice if the function would do it for you.
Example:
# using named args
glue("Hello {firstname} {lastname}", firstname="John", lastname="Doe")
person <- c(firstname="John", lastname="Doe")
# Trying to pass a named vector as .envir doesn't workglue("Hello {firstname} {lastname}", .envir=person)
# Must do this instead
glue("Hello {firstname} {lastname}", .envir=as.environment(as.list(person)))
The .envir arg should probably satisfy rlang::is_dictionary
if it isn't an environment.
E.g something like:
f('my name is {name}, but do not \\{messwiththis\\}')
or (better since less typing and also concordant with what Python does):
f('my name is {name}, but do not {{messwiththis}}')
wherein the {{
would get replaced by {
.
Happy to help with PR if you want help.
Great feature! I was wondering if it should happen before the command substitution. Because right now I get:
l <- list(a = list(a1 = 1, a2 = 2, a3 = 3), b = "foo")
cat(yaml::as.yaml(l))
#> a:
#> a1: 1.0
#> a2: 2.0
#> a3: 3.0
#> b: foo
glue("
# Indented a bit in the code, but not in the output
{ yaml::as.yaml(l) }
")
#> # Indented a bit in the code, but not in the output
#> a:
#> a1: 1.0
#> a2: 2.0
#> a3: 3.0
#> b: foo
Would you be willing to bump past the CRAN version? I'm using things that were added since then and want to capture that in DESCRIPTION. I already have glue in Remotes but feel like I should also state that version must be greater than 1.0.0.
install.packages("devtools")
trying URL 'https://mirrors.ebi.ac.uk/CRAN/bin/windows/contrib/3.4/devtools_1.13.2.zip'
Content type 'application/zip' length 442517 bytes (432 KB)
downloaded 432 KB
package 'devtools' successfully unpacked and MD5 sums checked
The downloaded binary packages are in
C:\Users\edguevara\AppData\Local\Temp\Rtmp4gSnoj\downloaded_packages
library(tidyverse)
Error: package or namespace load failed for 'tidyverse' in loadNamespace(j <- i[[1L]], c(lib.loc, .libPaths()), versionCh
eck = vI[[j]]):
there is no package called 'glue'
devtools::install_github("tidyverse/glue")
Downloading GitHub repo tidyverse/glue@master
from URL https://api.github.com/repos/tidyverse/glue/zipball/master
Error: running command '"C:/PROGRA1/R/R-341.0/bin/x64/R" --no-site-file --no-environ --no-save --no-restore --quiet CMD
config CC' had status 1
It would be simpler to only accept delimiters of length 1.
It feels like collapse()
would be more consistent with glue()
(and more convenient) if it returned character(0)
if the input has length zero.
library(glue)
glue("{x}", x = "hi")
#> hi
glue("{x}", x = character(0))
#> character(0)
collapse(x = c("hi", "bye"), last = " and ")
#> [1] "hi and bye"
collapse(x = c(NULL, "bye"), last = " and ")
#> [1] "bye"
collapse(x = c("hi", NULL), last = " and ")
#> [1] "hi"
collapse(x = NULL, last = " and ")
#> [1] ""
collapse(x = character(), last = " and ")
#> [1] ""
Set of helpers
collapse <- function(x, sep = "") paste(x, collapse = sep)
Hi, thanks for providing a great package.
Do you have any plan in mind to release this fstrings library on CRAN?
I'm thinking about importing your library in my library.
When any expression (but the last) is NULL then glue
returns an empty character vector. In case the last expression is NULL it ignores the last expressions and returns the result of the other expressions.
library(glue)
empty <- c()
glue(empty, 1)
glue(1, empty)
#> 1
glue(1, 2, empty)
#> 12
glue(1, empty, 0)
glue("{empty}", 1)
glue(1, "{empty}")
glue(1, "{empty}", 0)
A version of glue()
that automatically quotes results, useful for constructing SQL queries.
I'm trying to use glue to make bulleted lists for messages. I'm a bit puzzled. Maybe this is #47?
I don't understand why I lose the two spaces before the asterisk, as it's not leading whitepace of the first line.
glue::glue("The stuff before the bullet list
* one bullet")
#> The stuff before the bullet list
#> * one bullet
Adding a new line at the start helps, but I'm not sure why, because now the bulleted line is the 3rd (and last) line.
glue::glue("
The stuff before the bullet list
* one bullet")
#> The stuff before the bullet list
#> * one bullet
Adding a new line to the end doesn't help, but I though it might, because it makes my bulleted line NOT the last line.
glue::glue("The stuff before the bullet list
* one bullet
")
#> The stuff before the bullet list
#> * one bullet
I would like to do
iris %>% mutate(glued_stuff = glue("This {Species} has a petal length of {Petal.Length}"))
instead of
iris %>% mutate(glued_stuff = glue_data(., "This {Species} has a petal length of {Petal.Length}"))
What do you think about this?
I apologize in advance if this is me not understanding how to use these tools appropriately. But the intention is to have a nicer replacement to paste0("sth_", quo_name(expr)
because when it is more complicated than just a prefix or suffix paste/0 is hella ugly and to read.
library(rlang)
library(glue)
glue
+ rlang
= 😞glue_quo <- function(expr) {
expr <- enquo(expr)
glue("expr name is {expr}", quo_name(expr))
}
glue_quo(expr = 3)
#> expr name is ~3
#> expr name is 33
devtools::session_info()
#> Session info -------------------------------------------------------------
#> setting value
#> version R version 3.4.0 (2017-04-21)
#> system x86_64, darwin15.6.0
#> ui X11
#> language (EN)
#> collate en_CA.UTF-8
#> tz America/Vancouver
#> date 2017-05-20
#> Packages -----------------------------------------------------------------
#> package * version date source
#> backports 1.0.5 2017-01-18 CRAN (R 3.4.0)
#> base * 3.4.0 2017-04-21 local
#> compiler 3.4.0 2017-04-21 local
#> datasets * 3.4.0 2017-04-21 local
#> devtools 1.13.1 2017-05-13 CRAN (R 3.4.0)
#> digest 0.6.12 2017-01-27 CRAN (R 3.4.0)
#> evaluate 0.10 2016-10-11 CRAN (R 3.4.0)
#> glue * 1.0.0 2017-05-21 Github (tidyverse/glue@41a5cff)
#> graphics * 3.4.0 2017-04-21 local
#> grDevices * 3.4.0 2017-04-21 local
#> htmltools 0.3.6 2017-04-28 CRAN (R 3.4.0)
#> knitr 1.15.20 2017-05-02 Github (yihui/knitr@f3a490b)
#> magrittr 1.5 2014-11-22 CRAN (R 3.4.0)
#> memoise 1.1.0 2017-04-21 CRAN (R 3.4.0)
#> methods * 3.4.0 2017-04-21 local
#> Rcpp 0.12.10 2017-03-19 CRAN (R 3.4.0)
#> rlang * 0.1.1.9000 2017-05-21 Github (tidyverse/rlang@7c2f7e8)
#> rmarkdown 1.5 2017-04-26 CRAN (R 3.4.0)
#> rprojroot 1.2 2017-01-16 CRAN (R 3.4.0)
#> stats * 3.4.0 2017-04-21 local
#> stringi 1.1.5 2017-04-07 CRAN (R 3.4.0)
#> stringr 1.2.0 2017-02-18 CRAN (R 3.4.0)
#> tools 3.4.0 2017-04-21 local
#> utils * 3.4.0 2017-04-21 local
#> withr 1.0.2 2016-06-20 CRAN (R 3.4.0)
#> yaml 2.1.14 2016-11-12 CRAN (R 3.4.0)
glue::glue("{1:3}")
#> 1
#> 2
#> 3
glue::glue(1:3)
#> Error: All unnamed arguments must be length 1
Can the two expressions be made equivalent? This will simplify the transition from paste0()
.
{
}
would make it hard to work with some languages such as TeX.
Can we have lst()
or tibble()
semantics?
glue::glue("{b}", a = 1, b = a)
#> Error in eval(expr, envir, enclos): object 'a' not found
Expected result: "1"
When the .x
argument of glue_data()
is an environment, the evaluation of ...
takes place in .x
and not in .envir
, contrary to the documented role of .envir
. In particular, if ...
is not in .x
, then glue_data()
will fail.
Is this the intended behavior?
Example:
env <- new.env(parent = baseenv())
env$a <- "This is 'a'"
text <- "{a}"
glue_data(.x = env, text)
## Error in eval(x, envir = data, enclos = envir) : object 'text' not found
glue_data()
has not evaluated text
in .envir = parent.frame()
.
Naively, I would expect .x
to be used solely for object look-up, i.e., as if .x
were coerced to a list:
glue_data(.x = as.list(env), text)
## This is 'a'
I think it is good practice.
Glue is not working properly with UTF-8 encoded strings.
> x = "pão"
> x
[1] "pão"
> Encoding(x)
[1] "latin1"
> glue("{x}")
pão
> x = enc2utf8("pão")
> x
[1] "pão"
> Encoding(x)
[1] "UTF-8"
> glue("{x}")
pão
Ping me once you have the logo and I'll give you the details (which we should write up somewhere)
Are there any plans of adding formatters?
To clarify, by “formatter” I mean (1) an interface and (2) a glue syntax that advanced formatting of glue tokens. Here’s an example:
glue('π = {pi}')
glue('π to two decimal places = {format(pi, digits = 3)}')
With formatters, the second line could be for instance written as
glue('π to two decimal places = {pi:0.2}')
Many libraries offer similar capabilities, for instance composite formatting in .NET.
Ideally this would be extensible, allowing users to register their own formatters. For instance the following is thinkable:
arrgh_glue = function (str, options) {
gsub('r', 'R', str)
}
# optionally, though ideally not necessary:
# register_glue_formatter(arrgh = arrgh_glue)
name = 'Konrad'
glue('Hello, {name:arrgh}!')
# Hello, KonRad!
The .NET documentation has some more examples that show the scope of what could be possible.
e.g.
f(
'My name is {name},',
' my age next year is {age + 1},',
' my anniversary is {format(anniversary, "%A, %B %d, %Y")}.',
name = "Fred",
age = 50,
anniversary = as.Date("1991-10-12")
)
cat_string <- function(x) {
stopifnot(is.character(x))
structure(x, class = "cat_string")
}
print.cat_string <- function(x, ..., sep = "\n") {
cat(x, ..., sep = sep)
}
https://github.com/joshuaulrich/rchk-docker should be useful
Running the example for glue_sql
in the README throws the error:
Error in glue_sql("\n SELECT {var
}\n FROM {tbl
}\n WHERE {tbl
}.sepal_length > {num}\n AND {tbl
}.species = {val}\n ", :
could not find function "glue_sql"
I need to run glue::glue_sql for it to work.
Aside from the change in class, glue()
acts as the identity function on strings without expressions, except the empty string: glue("")
gives character(0)
.
Is this exception intended?
A few years ago I asked this question on SO
http://stackoverflow.com/questions/16595621/error-safe-templating-with-brew-whisker
The problem is summarised as follows: given 1) a template string, 2) a named list of values, insert those values in the template (with evaluation of R code), but return an error if one or more named values are missing. The solutions with brew or whisker were not particularly elegant.
I think glue provides a good alternative, but it would be nice to have a helper function that automatically enables checking of absent values in the environment (and get their name in the error message).
library(glue)
data <- list( name = "Chris", value= 124)
do.call(glue, list('Hello {name} You have just won ${value}!', .envir=as.environment(data)))
# Hello Chris You have just won $124!
do.call(glue, list('Hello {name} You have just won ${value}!', .envir=as.environment(data[-1])))
# Error in eval(expr, envir, enclos) : object 'name' not found
Inputs are not vectorized
I'm puzzled by this statement in the main help file. The example mtcars %>% glue_data("{rownames(.)} has {hp} hp")
seems to immediately go counter to this (not to mention lots of usage I've made). Can this be reworded so the meaning is more clear?
Seems glue
corrupt the input string with space or tabs at begin.
I tried with CRAN and git version of the package.
devtools::install_github("tidyverse/glue")
cyr <- 2017
period <- 2
rows_limit <- 1000
x <- glue::glue('SELECT MIN_MEAN_QUANTITY_OUT,
MIN_MEAN_QUANTITY_IN,
MAX_MEAN_PRICE_OUT,
MAX_MEAN_PRICE_IN
FROM LOAD_BOUNDS_BY_YM_NROWS
WHERE YEAR = {cyr}
AND MONTH = {period - 1}
AND MIN_NUM_OF_ROWS_PQ = {rows_limit}')
x
Output:
SELECT MIN_MEAN_QUANTITY_OUT,
MIN_MEAN_QUANTITY_IN,
MAX_MEAN_PRICE_OUT,
MAX_MEAN_PRICE_IN
LOAD_BOUNDS_BY_YM_NROWS
YEAR = 2017
MONTH = 1
MIN_NUM_OF_ROWS_PQ = 1000
FROM
WHERE
, AND
are missing in the result.
Session info:
R version 3.4.0 (2017-04-21)
Platform: x86_64-pc-linux-gnu (64-bit)
Running under: Arch Linux
Matrix products: default
BLAS: /usr/lib/R/lib/libRblas.so
LAPACK: /usr/lib/R/lib/libRlapack.so
locale:
[1] LC_CTYPE=ru_RU.UTF-8 LC_NUMERIC=C LC_TIME=ru_RU.UTF-8 LC_COLLATE=C
[5] LC_MONETARY=ru_RU.UTF-8 LC_MESSAGES=ru_RU.UTF-8 LC_PAPER=ru_RU.UTF-8 LC_NAME=C
[9] LC_ADDRESS=C LC_TELEPHONE=C LC_MEASUREMENT=ru_RU.UTF-8 LC_IDENTIFICATION=C
attached base packages:
[1] stats graphics grDevices utils datasets methods base
loaded via a namespace (and not attached):
[1] compiler_3.4.0 tools_3.4.0 parallel_3.4.0 glue_1.1.1.9000
paste0()
and sprintf()
treat NA_character_
as "NA":
sv = c(809, NA_character_, "help")
paste0(sv, ".io")
#> [1] "809.io" "NA.io" "help.io"
sprintf("%s.io", sv)
#> [1] "809.io" "NA.io" "help.io"
Not sure if it's intended, but glue::glue()
also fails to suppress NA
:
glue::glue("{sv}.io")
#> 809.io
#> NA.io
#> help.io
stringr::str_c
performs better:
stringr::str_c(sv, ".io")
#> [1] "809.io" NA "help.io"
x <- character()
glue::glue("{x}")
#> Error: Variables must be length 1 or 1
I think this should return an empty character vector.
> f('my name is {name}, but do not \\{messwiththis\\}')
Error in fstring_(x, function(x) paste(collapse = sep, fun(eval(parse(text = x), :
<text>:1:13: unexpected input
1: messwiththis\
^
Seems to be an fstrings thing since the following parses fine:
> 'my name is {name}, but do not \\{messwiththis\\}'
[1] "my name is {name}, but do not \\{messwiththis\\}"
Also happy to help if you want help.
I have CI set up on gitlab for my package builds. When I started using glue, I get the following segfaults (I am posting the output of all the jobs):
Running with gitlab-ci-multi-runner 1.11.1 (a67a225)
on dev (9d172ed6)
Using Shell executor...
Running on AnalyticsDevVM...
Fetching changes...
Removing TTdashboard.Rcheck/
Removing TTdashboard_0.2.39.tar.gz
HEAD is now at 538f5eb Merge branch '73-sac-tooltip-missing-total' into 'dev'
Checking out 538f5ebf as dev...
Skipping Git submodules setup
$ awk '{sub(/quick/, "all"); print}' tests/testthat.R > tests/tmp.R
$ mv tests/tmp.R tests/testthat.R
$ R -e "cov<-covr::package_coverage(type='all');print(cov);covr::report(cov,file='index.html',browse=FALSE)"
R version 3.3.2 (2016-10-31) -- "Sincere Pumpkin Patch"
Copyright (C) 2016 The R Foundation for Statistical Computing
Platform: x86_64-pc-linux-gnu (64-bit)
R is free software and comes with ABSOLUTELY NO WARRANTY.
You are welcome to redistribute it under certain conditions.
Type 'license()' or 'licence()' for distribution details.
Natural language support but running in an English locale
R is a collaborative project with many contributors.
Type 'contributors()' for more information and
'citation()' on how to cite R or R packages in publications.
Type 'demo()' for some demos, 'help()' for on-line help, or
'help.start()' for an HTML browser interface to help.
Type 'q()' to quit R.
> cov<-covr::package_coverage(type='all');print(cov);covr::report(cov,file='index.html',browse=FALSE)
Error: Failure in `/tmp/RtmpJdZkqe/R_LIBS3d672089871e/TTdashboard/TTdashboard-tests/testthat.Rout.fail`
> library(testthat)
> library(TTdashboard)
>
> test_check("TTdashboard", filter = "all")
*** caught segfault ***
address 0x30, cause 'memory not mapped'
Traceback:
1: .Call(to_impl, unnamed_args, function(expr) as.character(eval2(parse(text = expr), envir = env, data = .x)))
2: glue_data(NULL, ..., .sep = .sep, .envir = .envir)
3: glue::glue("SELECT ScenarioId, {flexcol} CountryId, FactorId, YearId, DataValue\n FROM {table}\n USE INDEX ({xbindex})\n WHERE {fixedcol} = {fixed} AND\n {specific_col} = {specific_value} AND\n ScenarioOriginId = {scenario_origin} AND\n ScenarioId = {globals$scenarioId} AND\n {flexcol} In ({flex_cntrs})", flex_cntrs = collapse(flex, ","))
4: eval(expr, envir, enclos)
5: eval(lhs, parent, parent)
6: glue::glue("SELECT ScenarioId, {flexcol} CountryId, FactorId, YearId, DataValue\n FROM
Execution halted
ERROR: Job failed: exit status 1
This happens from time to time, usually the CI job completes without errors on retry. Here is my devtools:session_info()
output:
> devtools::session_info()
Session info -------------------------------------------------------------------
setting value
version R version 3.3.2 (2016-10-31)
system x86_64, linux-gnu
ui X11
language (EN)
collate en_US.UTF-8
tz <NA>
date 2017-04-25
Packages -----------------------------------------------------------------------
package * version date source
devtools 1.12.0 2016-06-24 CRAN (R 3.3.0)
digest 0.6.10 2016-08-02 cran (@0.6.10)
glue * 0.0.0.9000 2017-03-29 Github (tidyverse/glue@099b283)
memoise 1.0.0 2016-01-29 CRAN (R 3.3.0)
withr 1.0.2 2016-06-20 CRAN (R 3.3.0)
Any ideas on how to debug further?
.na = "NA"
by default. If NULL
, then 'NA's are propagated (as they currently are in devel).
Would it make sense for
glue::glue("foo bar \
baz")
to be equivalent to
glue::glue("foo bar baz")
so long messages can be broken down in several lines in the code?
Thanks for this great package. glue made my life easier with template strings.
But, one thing I feel a bit frustrated is that some S3 generic methods cannot process the glue object because they don't know the fact glue
is almost character
.
generate_msg <- function(x) {
l <- list(msg = glue::glue('Praise the {x}!'))
jsonlite::toJSON(l)
}
generate_msg("V8")
#> Error: No method asJSON S3 class: glue
class(glue::glue('Praise the {x}!', x = 'V8'))
#> [1] "glue"
I know just using unclass()
or as.character
will save me, but is it possible to let glue
class inherit from character
class? Or, are there some reason that we have to restrict its class glue
only?
generate_msg <- function(x) {
msg <- `class<-`(glue::glue('Praise the {x}!'), c('glue', 'character'))
l <- list(msg = msg)
jsonlite::toJSON(l)
}
generate_msg("V8")
#> {"msg":["Praise the V8!"]}
With option to truncate (and insert ...
)
f$"my name is {name}"
could work. Just class f
and add a $
method like gsubfn
does. Could also provide a different fun to avoid issues (e.g. F
).
Saves a keystroke and also looks a tiny bit more like the python syntax.
This one is obviously low priority, but kind of cute, and different to the one I tweeted about.
Perhaps an installation command is looking for a previous version of R?
> devtools::install_github('tidyverse/glue')
Downloading GitHub repo tidyverse/glue@master
from URL https://api.github.com/repos/tidyverse/glue/zipball/master
Error: running command '"C:/PROGRA~1/R/R-33~1.3/bin/x64/R" --no-site-file --no-environ --no-save --no-restore --quiet CMD config CC' had status 127
> sessionInfo()
R version 3.3.3 (2017-03-06)
Platform: x86_64-w64-mingw32/x64 (64-bit)
Running under: Windows 10 x64 (build 14393)
locale:
[1] LC_COLLATE=English_United States.1252
[2] LC_CTYPE=English_United States.1252
[3] LC_MONETARY=English_United States.1252
[4] LC_NUMERIC=C
[5] LC_TIME=English_United States.1252
attached base packages:
[1] stats graphics grDevices utils datasets methods base
loaded via a namespace (and not attached):
[1] httr_1.2.1 R6_2.2.0 tools_3.3.3 withr_1.0.2
[5] curl_2.4 memoise_1.0.0 git2r_0.18.0 digest_0.6.12
[9] devtools_1.12.0
It should trim including the last line.
t <- glue:::trim
t("
Hello,
World.
")
# should be the following (based on the indention of the last line)
# " Hello,\n World."
# Actually is
#> "Hello,\nWorld."
It appears that NA_character_
values are (erroneously?) special when using the new .na=NULL
option in v1.2.0.
## FYI: dbconn is a RPostgres DBI connection
> dbconn <- DBI::dbConnect(RPostgres::Postgres(), host = myhost, dbname = mydb, user = me)
## a bunch of NAs of different type:
> l <- list(
lgl = NA
,chr = NA_character_
,dbl = NA_real_
,int = NA_integer_
)
## first without the default .na = "NA" option:
> map_chr(l, function(x) glue_sql("foo = {x}", .con = dbconn))
lgl chr dbl int
"foo = NA" "foo = 'NA'" "foo = NA" "foo = NA"
## now with .na = NULL, which should return _just_ <NA> for all four inputs:
> map_chr(l, function(x) glue_sql("foo = {x}", .con = dbconn, .na = NULL))
lgl chr dbl int
NA "foo = 'NA'" NA NA
This appears to be specific to glue_sql
, glue
itself works as expected for all NA types.
Is this related to glue_sql
or perhaps the underlying DBI calls? (FWIW I've tried with both RPostgres and RPostgreSQL and found identical results.)
bar <- 'baz'
microbenchmark(glue::glue('foo{bar}'))
# Unit: microseconds
# expr min lq mean median uq max neval
# glue::glue("foo{bar}") 291.851 343.165 433.5618 401.78 555.0745 753.867 100
microbenchmark(paste0('foo', bar))
# Unit: microseconds
# expr min lq mean median uq max neval
# paste0("foo", bar) 2.45 2.523 3.05519 2.6085 2.8555 36.524 100
microbenchmark(sprintf('foo%s', bar))
# Unit: nanoseconds
# expr min lq mean median uq max neval
# sprintf("foo%s", bar) 825 947.5 1273.85 1111.5 1184.5 19195 100
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.