You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Current chunks version generates multiple problems. The most important is that:
Chunks is an R6 object which is not mutable. This means that changes in the chunks don't trigger shiny reactivity. To achieve this we need to clone or force some reactive events using reactive fields kept in chunks
Partial consequence of above is that chunks having queue system which delays evaluation of the code. This causes the mismatch between code evaluation and reactivity and creates general confusion.
Problem with chunks object in the session is a minor and can be solved in the easy yet time consuming way Deprecate init_chunks #22
Solution is to refactor chunks to S4 object which will be "reactive" by default - changing any slots in the S4 object changes the address of the S4 object.
class code
setClass(
"Quosure",
representation(expr="expression", env="environment"),
prototype(expr= expression(), env= new.env(parent= parent.env(.GlobalEnv)))
)
setGeneric("push", function(object, expr, name = "code") {
standardGeneric("push")
})
setGeneric("get_var", function(object, var) {
standardGeneric("get_var")
})
setGeneric("get_code", function(object, deparse = FALSE) {
standardGeneric("get_code")
})
setGeneric("join", function(object, object2) {
standardGeneric("join")
})
setMethod("push", signature("Quosure"), function(object, expr, name) {
# combine expressionsnm<- make.unique(c(names(object@expr), name))
object@expr<- setNames(c(object@expr, expr), nm)
# need to copy the objects from old env to new env# to avoind "chunks" sharing the same environmentenv<- new.env()
for (iin ls(object@env)) {
env[[i]] <-object@env[[i]]
}
eval(expr, envir=env)
object@env<-envobject
})
setMethod("get_var", signature("Quosure", "character"), function(object, var) {
get(var, envir=object@env)
})
setMethod("get_code", signature("Quosure"), function(object, deparse) {
if (deparse) {
deparse(object@expr)
} else {
object@expr
}
})
setMethod("join", signature("Quosure", "Quosure"), function(object, object2) {
# object2 can't have modified object of the same name! See chunks_push_chunkscommon_names<- intersect(ls(object@env), ls(object2@env))
is_identical_obj<- vapply(common_names, function(x) {
identical(get(x, object@env), get(x, object2@env))
}, logical(1))
if (any(isTRUE(is_identical_obj))) {
stop(
"join does not allow overwriting already calculated values.",
" Following variables would have been overwritten:",
paste(" -", names(is_identical_obj), collapse="\n"),
sep="\n"
)
}
# join expressions# > join should be an inteligent unionunique_expr<-!(object2@expr%in%object@expr& names(object2@expr) %in% names(object2@expr))
# duplicated expr will probably have the same name also# unique_expr should have TRUE only at the end of the vector.object@expr<- c(object@expr, object2@expr[unique_expr])
# insert new objects to envnew_names<- setdiff(ls(object2@env), ls(object@env))
lapply(new_names, function(x) assign(x, get(x, object2@env), object@env))
object
})
Above class works as expected:
each push evaluates new code.
on each push new environment is created.
even if new environment is created, unchanged object are not deep copied.
mutated object within one environment does not change "itself" in the other environments.
library(rlang)
Code<- new("Quosure")
Code1<- push(Code, quote(a<-data.frame(a=1)))
Code2<- push(Code1, quote(ADSL<-data.frame(a=1, b=2)))
Code3<- push(Code2, quote(ADSL$c<-3))
lobstr::obj_addr(Code)
lobstr::obj_addr(Code2) # new addresslobstr::obj_addr(Code2) # new addresslobstr::obj_addr(Code3) # new addresslobstr::obj_addr(Code@env) # new environmentlobstr::obj_addr(Code1@env) # new environmentlobstr::obj_addr(Code2@env) # new environmentlobstr::obj_addr(Code3@env) # new environmentlobstr::obj_addr(Code1@env$a)
lobstr::obj_addr(Code3@env$a) # unchanged object in new env preserves the same pointerlobstr::obj_addr(Code2@env$ADSL)
lobstr::obj_addr(Code3@env$ADSL) # mutated object changes it's reference
get_var(Code2, "ADSL")
get_var(Code3, "ADSL")
POC for a shiny app:
Diagram of simple app representing different use cases:
Current chunks version generates multiple problems. The most important is that:
Chunks is an R6 object which is not mutable. This means that changes in the chunks don't trigger shiny reactivity. To achieve this we need to clone or force some reactive events using reactive fields kept in chunks
Partial consequence of above is that chunks having queue system which delays evaluation of the code. This causes the mismatch between code evaluation and reactivity and creates general confusion.
Problem with chunks object in the session is a minor and can be solved in the easy yet time consuming way Deprecate init_chunks #22
Solution is to refactor chunks to S4 object which will be "reactive" by default - changing any slots in the S4 object changes the address of the S4 object.
class code
Above class works as expected:
POC for a shiny app:
Diagram of simple app representing different use cases:
App code
The text was updated successfully, but these errors were encountered: