Skip to content

Syntax changes for shinymeta 0.2.0

Joe Cheng edited this page Aug 12, 2019 · 1 revision

In shinymeta 0.2.0, we made a very significant breaking change to the syntax you use to annotate code in meta reactive objects.

I'm very sorry we made this change after making shinymeta public, and after I even gave a talk about it at the useR2019 conference. It was only through user feedback that we realized what a severe problem the previous syntax had.

Previous syntax

When shinymeta was initially made public, you would use the !! (pronounced "bang-bang") operator. Like so:

# Obsolete shinymeta 0.1.0 syntax
r <- metaReactive({
  head(data(), !!input$nrow)
})

The effect of this !! was as follows:

  • When r() is called normally, then the meta reactive's code block is first searched for !! expressions; those expressions are evaluated, with the result being placed back in the code block. Then the code block is executed. In this example, if the value of input$nrow is 5, then the actual code that is executed will be head(data(), 5).
  • When r() is asked to produce its code, the same thing happens, except instead of being executed, the code is returned. In this example, the code that is returned will be head(data(), 5).

New syntax

With shinymeta 0.2.0, the ..() (pronounced "dot-dot") function is used instead:

r <- metaReactive({
  head(data(), ..(input$nrow))
})

The effect of ..() is very subtly different.

  • When r() is called normally, the meta reactive's code block is first searched for ..() expressions, and those expressions have ..() stripped off but are otherwise unchanged. Then the code block is executed. In this example, the code that is executed will be head(data(), input$nrow).
  • When r() is asked to produce its code, it's actually similar to the 0.1.0 behavior; the ..() expressions are evaluated, and their results are inserted into the code block. In this example, the code that is returned will be head(data(), 5), same as before.

Why was this needed?

There were several issues with the old syntax:

  1. The !! operator had too many jobs. Its original purpose is for unquoting with tidyeval-aware packages like dplyr, and then we added unquoting for shinymeta. Because these two usages were so similar, and both built on top of tidyeval (at the time), I thought we could get away with using the same !! operator for both; but it doesn't work. The upshot was that using !! for shinymeta purposes made it nearly impossible to also use !! for dplyr purposes in the same app. With a dedicated ..() syntax for shinymeta, we no longer have this ambiguity.

  2. The behavior of !! in 0.1.0 was to replace the unquoted expression with its value--for example, print(!!letters[1:5]) would become print(c("a", "b", "c", "d", "e")). This is only correct if the code in question displays referential transparency, but R has many functions that use non-standard evaluation in ways that are not at all referentially transparent. For example, the plot function determines its default axes labels based on NSE, and lm does something similar. This problem was pointed out by @zappingseb in Issue #53, where shinymeta unquoting caused lm output to look like garbage.

Clone this wiki locally