Help understanding Shiny function syntax: expression objects and curly brackets

I've gone through some Shiny tutorials. I can produce simple apps, but I have a difficult time extending past the examples. The Shiny code isn't like the R code I'm used to reading and writing.

My first question is: why are there curly brackets inside the parentheses in this line of code?

  output$table <- renderTable({
    d()
  })

I see that renderTable wants an expression object as its input argument. What is the relationship between the curly brackets and expressions? Is the input argument to renderTable coerced to an expression? To be honest, I've never encountered expression objects before.

In this second example, why is the variable output listed as an input argument to function? Why is there no return argument? Why again are there curly brackets inside the call to renderPlot?

Many thanks! And apologies for the very general questions.

 shinyServer(function(input, output) {
    output$distPlot <- renderPlot({

        # generate bins based on input$bins from ui.R
        x    <- faithful[, 2]
        bins <- seq(min(x), max(x), length.out = input$bins + 1)

        # draw the histogram with the specified number of bins
        hist(x, breaks = bins, col = 'darkgray', border = 'white')

    })

})

The 2 first videos in the following link are great (this is an understatement) resources to understand the principles of shiny:
https://www.rstudio.com/resources/webinars/shiny-developer-conference/

From an purely R perspective, {} delimit an expression. In the context of shiny, they still delimit an expression but also helps ensure that reactivity is handle correctly.

3 Likes

These are good questions. I agree with @pomchip's recommendation to watch those videos--I worked very hard on that presentation and it contains the best explanation I've been able to come up with, for how and why Shiny works the way it does.

For the curly braces, several constructs in Shiny (renderXXX, reactive(), and observe()) operate on code blocks you pass them. Generally, when you pass arguments to a function, you expect that what the function cares about is the result of evaluating that argument. But with these Shiny constructs, instead, the expression you pass in is captured using non-standard evaluation. This is critical, because Shiny needs to execute that { d() } code not just once, but many times as the value of d() changes. The curly braces are not actually required, you could do renderTable( d() ) if you wanted to, but the braces make it feel more like a function.

For the second example, you're passing an anonymous function with parameters input and output into shinyServer. This is just boilerplate, but if you really want to know what's happening, this is just you telling Shiny what to do when a new session is created (i.e. a browser visits the app). These input and output objects are implemented by Shiny. When you assign to sub-variables of the output, there's no immediate value returned, but this is you telling Shiny to remember the recipe for populating that particular output (in this case, the one named distPlot).

In this second example, the curly braces are actually required for the renderPlot code block. This is because the code block is made up of three distinct expressions (assigning to x, assigning to bins, and calling hist), and whenever you have a function argument that's more than just a single expression, you need to use curly braces (you'll get a parse error if you omit the curly braces and try to run this code). There's no return in this case because the way hist() works is by writing to R's current graphics context--which you can think of as the graphical equivalent of printing text to the console.

Again, I'd watch the videos, things will hopefully make a lot more sense after that!

9 Likes

Thank you very much for the detailed explanation! I will definitely watch the videos. Best regards.

This topic was automatically closed 21 days after the last reply. New replies are no longer allowed.

If you have a query related to it or one of the replies, start a new topic and refer back with a link.