-
Notifications
You must be signed in to change notification settings - Fork 14
Meta Mode
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
}