Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Polish README and introduction to glue #337

Merged
merged 8 commits into from
Aug 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
150 changes: 50 additions & 100 deletions README.Rmd
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,8 @@ library(glue)
[![test-coverage](https://github.com/tidyverse/glue/actions/workflows/test-coverage.yaml/badge.svg)](https://github.com/tidyverse/glue/actions/workflows/test-coverage.yaml)
<!-- badges: end -->

## Overview

Glue offers interpreted string literals that are small, fast, and dependency-free. Glue does this by embedding R expressions in curly braces which are then evaluated and inserted into the argument string.
glue offers interpreted string literals that are small, fast, and dependency-free.
glue does this by embedding R expressions in curly braces, which are then evaluated and inserted into the string.

## Installation

Expand All @@ -49,136 +48,87 @@ pak::pak("tidyverse/glue")
library(glue)

name <- "Fred"
glue('My name is {name}.')

# A literal brace is inserted by using doubled braces.
name <- "Fred"
glue("My name is {name}, not {{name}}.")
glue("My name is {name}.")
```

`glue::glue()` is also made available via `stringr::str_glue()`.
So if you've already attached stringr (or perhaps the whole tidyverse), you can access `glue()` like so:
`stringr::str_glue()` is an alias for `glue::glue()`.
So if you've already attached stringr (or perhaps the whole tidyverse), you can use `str_glue()` to access all of the functionality of `glue()`:

```{r eval = FALSE}
library(stringr) # or library(tidyverse)

stringr_fcn <- "`stringr::str_glue()`"
glue_fcn <- "`glue::glue()`"

str_glue('{stringr_fcn} is essentially an alias for {glue_fcn}.')
#> `stringr::str_glue()` is essentially an alias for `glue::glue()`.
name <- "Wilma"
str_glue("My name is {name}.")
#> My name is Wilma.
```

`glue_data()` works well with pipes:
You're not limited to using a bare symbol inside `{}`; it can be any little bit of R code:

```{r}
mtcars$model <- rownames(mtcars)
mtcars |> head() |> glue_data("{model} has {hp} hp")
name <- "Pebbles"
glue("Here is my name in uppercase and doubled: {strrep(toupper(name), 2)}.")
```

##### `glue_data()` is useful with [magrittr](https://cran.r-project.org/package=magrittr) pipes.
```{r}
`%>%` <- magrittr::`%>%`
head(mtcars) %>% glue_data("{rownames(.)} has {hp} hp")
```
### Data can come from various sources

##### `glue()` is useful within dplyr pipelines
```{r, message = FALSE}
library(dplyr)
head(iris) %>%
mutate(description = glue("This {Species} has a petal length of {Petal.Length}"))
```
glue can interpolate values from the local environment or from data passed in `name = value` form:

##### Leading whitespace and blank lines from the first and last lines are automatically trimmed.
This lets you indent the strings naturally in code.
```{r}
glue("
A formatted string
Can have multiple lines
with additional indention preserved
")
x <- "the local environment"
glue(
"`glue()` can access values from {x} or from {y}. {z}",
y = "named arguments",
z = "Woo!"
)
```

##### An additional newline can be used if you want a leading or trailing newline.
```{r}
glue("

leading or trailing newlines can be added explicitly
If the relevant data lives in a data frame (or list or environment), use `glue_data()` instead:

")
```

##### `\\` at the end of a line continues it without a new line.
```{r}
glue("
A formatted string \\
can also be on a \\
single line
")
mini_mtcars <- head(cbind(model = rownames(mtcars), mtcars))
glue_data(mini_mtcars, "{model} has {hp} hp.")
```

##### A literal brace is inserted by using doubled braces.
```{r}
name <- "Fred"
glue("My name is {name}, not {{name}}.")
```
`glue_data()` is very natural to use with the pipe:

##### Alternative delimiters can be specified with `.open` and `.close`.
```{r}
one <- "1"
glue("The value of $e^{2\\pi i}$ is $<<one>>$.", .open = "<<", .close = ">>")
mini_mtcars |>
glue_data("{model} gets {mpg} miles per gallon.")
```

##### All valid R code works in expressions, including braces and escaping.
Backslashes do need to be doubled just like in all R strings.
```{r}
`foo}\`` <- "foo"
glue("{
{
'}\\'' # { and } in comments, single quotes
\"}\\\"\" # or double quotes are ignored
`foo}\\`` # as are { in backticks
}
}")
```
These `glue_data()` examples also demonstrate that `glue()` is vectorized over the data.

### What you see is awfully close to what you get

`glue()` lets you write code that makes it easy to predict what the final string will look like.
There is considerably less syntactical noise and mystery compared to `paste()` and `sprintf()`.

##### `glue_sql()` makes constructing SQL statements safe and easy
Use backticks to quote identifiers, normal strings and numbers are quoted
appropriately for your backend.
Empty first and last lines are automatically trimmed, as is leading whitespace that is common across all lines.
You don't have to choose between indenting your code properly and getting the output you actually want.
Consider what happens when `glue()` is used inside the body of a function:

```{r}
con <- DBI::dbConnect(RSQLite::SQLite(), ":memory:")
colnames(iris) <- gsub("[.]", "_", tolower(colnames(iris)))
DBI::dbWriteTable(con, "iris", iris)

var <- "sepal_width"
tbl <- "iris"
num <- 2
val <- "setosa"
glue_sql("
SELECT {`var`}
FROM {`tbl`}
WHERE {`tbl`}.sepal_length > {num}
AND {`tbl`}.species = {val}
", .con = con)
foo <- function() {
glue("
A formatted string
Can have multiple lines
with additional indention preserved")
}
foo()
```

# Other implementations

Some other implementations of string interpolation in R (although not using identical syntax).
The leading whitespace that is common to all 3 lines is absent from the result.

- [stringr::str_interp](https://stringr.tidyverse.org/reference/str_interp.html)
- [R.utils::gstring](https://cran.r-project.org/package=R.utils)
- [rprintf](https://cran.r-project.org/package=rprintf)
## Learning more

String templating is closely related to string interpolation, although not
exactly the same concept. Some packages implementing string templating in R
include.
glue is a relatively small and focused package, but there's more to it than the basic usage of `glue()` and `glue_data()` shown here.
More recommended functions and resources:

- [whisker](https://cran.r-project.org/package=whisker)
- [brew](https://cran.r-project.org/package=brew)
- [jinjar](https://cran.r-project.org/package=jinjar)
* The "Get started" article (`vignette("glue")`) demonstrates more interesting features of `glue()` and `glue_data()`.
* `glue_sql()` and `glue_data_sql()` are specialized functions for producing SQL statements.
* glue provides a couple of custom knitr engines that allow you to use glue syntax in chunks; learn more in `vignette("engines", package = "glue")`.

## Code of Conduct

Please note that the glue project is released with a [Contributor Code of Conduct](https://glue.tidyverse.org/CODE_OF_CONDUCT.html). By contributing to this project, you agree to abide by its terms.
Please note that this project is released with a [Contributor Code of Conduct](https://glue.tidyverse.org/CODE_OF_CONDUCT.html).
By participating in this project, you agree to abide by its terms.
Loading
Loading