Closed vorpalvorpal closed 9 months ago
You can programmatically export names, using a similar workaround as for the programmatic import. As for import, there may in the future be an officially-supported, non-hacky way to achieve this. — But I can’t make promises.
Either way, the secret sauce is the function box::export()
which can (but generally should not) be used instead of the declarative (“roxygen-like”) export style.
I’ll show an example below but allow me to add a few notes about your code:
The declaration of imports <- lapply(c('...'), as.name)
is unnecessary: if you want to use wildcard imports, use ...
directly in the quoted expression, no need to splice in the list of imports:
bquote(./.(mod_name)[...])
I strongly advise against using here::here()
with ‘box’ (and in general). This is because here:here()
does generally not do what it advertises and only really works in RStudio project-based workflows, nowhere else.1 The fact that it works in your code is a pure coincidence — try changing your working directory, it will stop working. ‘box’ provides the function box::file()
, which will continue to work even after you change your working directory. In almost all cases, you want to use box::file()
instead of here::here()
. In your specific case, use box::file()
instead of here::here('R')
.
Don’t call stringr::str_c('./', .)
: you end up with the quoted expression ./`./mod_name`
, which is probably not what you expected, and I am actually now confused why this works — this is actually a bug in ‘box’ (and I will fix this bug, so this code will stop working in the future!).
Okay. Here’s how you can use box::export()
with dynamic names. I am assuming that you want to export all imported names (otherwise, adjust the exports
vector accordingly):
import_env <- parent.env(box::topenv())
exports <- setdiff(ls(import_env, all.names = TRUE), '%>%')
do.call(box::export, lapply(exports, as.name))
Please note that I have just found a bug in box::export()
which makes this fail for non-syntactic names (e.g. if you attempt to add %>%
to exports
you will get an error).
1 For more details please see the footnote in my comment at https://github.com/klmr/box/discussions/328#discussioncomment-6521485
Thank you for your very generous response. I will try this out.
I realize that this is all contrary to the philosophy of box
, but it seems necessary when trying to migrate a big messy existing project over to using box
.
Thank you again.
Please describe your feature request
This is almost certainly against the whole design philosophy of {box}, and yet...
As shown in issue 68, it is possible to load a bunch of modules programmatically, but it doesn't seem to then be possible to re-export them.
Background I have an r project. In it I have a folder named "R" that contains R scripts. I would like to have all functions defined in this directory that have an
@export
tag available to all other functions. Yes, I realise that this is not explicit, and is frowned upon, however this is an old project and there are a lot of functions defined that call each other.Partial solution Based on issue 68, I can create an
__init__.R
file in./R
and have it include the following:And this loads the functions just fine, however if I then add
box::use(PATH_TO_R_FOLDER)
to the top of a script, none of those functions called bybox::use
in__init__.R
are then available because there is not an export declaration in__init__.R
.If I add
#' @export
abovelist.files
I (unsurprisingly) get an error, and if I addbox::export(...)
I also get an error.I could write some logic to look through all the files found by
list.files
and search for "^(.*) <- function\(" and then export each of those function names, but that seems error-prone.