Circular imports? #346
-
My understanding might be flawed or are ciruclar imports supposed to be possible? I have a main.R that exports a and a module module.R that is called into main.R that exports b. Consequently module.R also imports c from main.R. I tried this but I get file does not exists error for main.R. I tried browser to check if the file exists and indeed How can I accomplish this. This is code I'm working on I decided to provide this example as my code does not work and demonstrates my goal. This is already a minimal example. I'm trying to create a reactive timer in shiny that I can import across various modules of my shiny app and refresh them all in sync. I hope someone more knowledgable can comment. main.R # https://community.rstudio.com/t/how-to-pause-edit-reactivetimer/176252/3
# This works but is not a module
box::use(shiny)
ui <- shiny$fluidPage(
shiny$numericInput(
"ms",
"millisec",
value = 300,
min = 100,
max = 2000,
step = 100
),
shiny$checkboxInput("chk", "on/off", value = TRUE),
shiny$verbatimTextOutput("display")
)
options(digits.secs = 6)
box::use(./timer[ mytimer ])
#' @export
timer_opts <- list(
ms = shiny$reactiveVal(NULL),
chk = shiny$reactiveVal(NULL)
)
server <- function(input, output, session) {
timer_opts$ms(shiny$req(input$ms))
timer_opts$chk(shiny$req(input$chk))
last_timer_value <- shiny$reactiveVal(NULL)
shiny$observeEvent(mytimer(), {
if(!identical(last_timer_value, mytimer())) {
if(shiny$isTruthy(mytimer())) {
last_timer_value(mytimer())
}
}
})
output$display <- shiny$renderText({
capture.output(shiny$req(last_timer_value()))
})
}
shiny$shinyApp(ui, server, options = list(port = 3003, launch.browser = FALSE)) timer.R box::use(shiny)
timer_func <- function(timer_opts) {
mytimer <- shiny$reactive({
millis <- shiny$req(timer_opts$ms())
shiny$invalidateLater(millis = millis)
if (!shiny$isTruthy(timer_opts$chk())) {
return(NULL)
}
return(Sys.time())
})
return(mytimer)
}
browser()
box::use(./main[ timer_opts ])
#' @export
mytimer <- timer_func(timer_opts)
|
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 4 replies
-
Circular imports are supported, but several important limitations apply. In particular, while a module is being loaded, it only exists partially. So while other modules can import it, they will see a “placeholder” until loading has finished. That placeholder defines names but cannot yet be used. However, I am not sure circularity is actually an issue here. In fact, when removing the circularity by inlining all code inside
(And |
Beta Was this translation helpful? Give feedback.
Hi @dereckmezquita, yes, that’s one of the limitations of circular modules: you cannot use any imported name while the module is still in a partial loading state. The lines
some_module <- something_from_main * 2
andprint(some_module)
are potentially problematic because they are attempting to use an imported name while the module the name is coming from is still being loaded.The easiest way of dealing with circular imports is to break the circle. In your example you could do this by putting
something_from_main
into a third module, which you then import in bothmain
andmodule
.However, you can use circular imports here, if you avoid that
some_module
is used during the (circular) import of…