Skip to content

Meta Mode

Joe Cheng edited this page Jul 9, 2019 · 3 revisions

One way to think of meta mode is as a state machine, where the nodes are "Normal", "Meta", and "Mixed", and the edges are withMetaMode, metaDispatch (i.e. entering a meta-reactive object), and metaExpr.

Normal is the default state, Mixed is when a metaReactive2 is executing but hasn't entered a metaExpr, and Meta is when you're in a metaExpr or directly inside expandObject/expandCode ("directly" meaning you haven't entered a metaReactive2).

(In the previous paragraph, consider metaReactive the same as metaReactive2 except there's no opportunity to put any code outside the metaExpr. Because that's what it is.)

When in Mixed mode, executing another metaReactive/metaReactive2 will cause that execution to happen under Normal mode. This makes it possible to do things like this:

df <- metaReactive({
  cars
})

df2 <- metaReactive2({
  req(nrows(df()) > 0)
  metaExpr(df() %>% sample_n(100))
})

In this example, df2 references df() both inside and outside of a metaExpr; in Normal mode, both executions should return data frames, while when df2() is invoked in Meta mode, the first call to df() needs to return a data frame (i.e. df must run in Normal mode) and the second call needs to return code.


(The lines marked with ** are the new and exciting edges added in PR #42)

Normal ==metaDispatch=> Normal
Normal ==metaExpr=> Normal

Meta ==metaDispatch=> Mixed **
Meta ==metaExpr=> Meta

Mixed ==metaDispatch=> Normal **
Mixed ==metaExpr=> Meta

For completeness (because this is the only way out of Normal) here are the ways withMetaMode() affects the state machine.

[Any] ==withMetaMode(TRUE)=> Meta
[Any] ==withMetaMode(FALSE)=> Normal
[Any] ==withMetaMode("mixed")=> Mixed

For reference: graphviz code for state machine

digraph metamodes {
  graph [layout = dot]

  node [fontname = "Helvetica", fontsize = "12pt"]
  edge [fontname = "Helvetica", fontsize = "12pt", minlen = 3]

  node [label = "Normal"]
  normal

  node [label = "Meta"]
  meta

  node [label = "Mixed"]
  mixed

  edge [label = "withMetaMode"]
  normal -> meta
  #meta   -> meta
  mixed  -> meta

  edge [label = "metaDispatch"]
  #normal -> normal
  meta   -> mixed
  mixed  -> normal

  edge [label = "metaExpr"]
  #normal -> normal
  #meta   -> meta
  mixed  -> meta
}
Clone this wiki locally