4

From this question, I gather that variables of the form {{var}} can be called echos in other programming languages, but I'm at a loss for why they do what they do in R.

Namely, I've used them within an RMarkdown template (here, state_template.Rmd) that is fed as input into a for loop in another script.

Example of filling in "placeholder" text with elements of a vector defined in another script:

Dear `r paste(contacts$firstname[contacts$state == {{eachstate}}], sep = ", ")`,`

This evaluates to the first name of the contact in each state of allstates passed to the for loop.

allstates <- state.abb

for (eachstate in allstates) {
    knit2html(input  = 'state_template.Rmd',
....
}
Community
  • 1
  • 1
mcjudd
  • 1,520
  • 2
  • 18
  • 33

1 Answers1

6

In your case, the {{ }} have no special meaning at all. You would get the same results with

Dear `r paste(contacts$firstname[contacts$state == eachstate], sep = ", ")`,

For example, in R, these are equivalent

a<-1:10
a[a%%2==1]
a[a%%2=={{1}}]
a[a%%2==((1))]

You can add extra parenthesis/braces without changing the meaning of the code in R. So in your case, running

sampleRmd<-'Dear `r paste(contacts$firstname[contacts$state == eachstate], sep = ", ")`'
knit(text=sampleRmd, quiet=T)

would work just the same. Just as the contacts variable is resolved to your current environment, so too is the eachstate variable. Using or not using the braces doesn't make a difference. If you directly call the function that parses the inline code blocks, it might be more obvious what's going on

knitr:::parse_only('paste(contacts$firstname[contacts$state == {{eachstate}}], sep = ", ")')
# expression(paste(contacts$firstname[contacts$state == {
#     {
#         eachstate
#     }
# }], sep = ", "))

The catch is that double braces are often used in "template" languages and knitr does allow you to define such templates. These templates are basically text chunks where you can swap out values in the text with values of variables in your current scope in R. This replacement is done by the knit_expand() function. Here's a minimal example in your case

sampleRmd<-'Dear `r paste(contacts$firstname[contacts$state == {{eachstate}}], sep = ", ")`'

contacts <- data.frame(
    firstname=c("Adam","Becky","Clement","David"),
    state=c("MI","CA","CA","MI")
)

eachstate <- "MI"
res <- knit_expand(text=sampleRmd)
res
# [1] "Dear `r paste(contacts$firstname[contacts$state == MI], sep = \", \")`"

Basically it just looks for anything between {{ and }} and replaces that with the value of the variable of the same name. In this case is replaces {{eachstate}} with the current value of the eachstate variable which is "MI" in this example. This is done before the R code is executed. Note that if you try to knit() this you will get an error

knit(text=res)
# Error in NextMethod("[") : object 'MI' not found

This is because the expand function has put in the literal value of MI as if it where a character string into the code. It did not quote the value. You would have to change the template to

sampleRmd<-'Dear `r paste(contacts$firstname[contacts$state == "{{eachstate}}"], sep = ", ")`'
res <- knit_expand(text=sampleRmd)
knit(text=res, quiet=T)
# [1] "Dear Adam, David"

But in your example, you are not taking advantage of any of the templating features. You're basically just adding unnecessary symbols to the R expression.

MrFlick
  • 195,160
  • 17
  • 277
  • 295
  • @Nicapyke I've updated my answer. Turns out I was wrong the first time. The braces actually do absolutely nothing in your example. – MrFlick Jan 09 '15 at 05:50
  • This is a superb answer, @MrFlick! Thanks so much for the thoughtful input. I'll pass along your knowledge... I had a slide ready to present on the use of `{{ }}`, and you explained the bit about their use in templating languages much better than I had. – mcjudd Jan 09 '15 at 22:21