I need a config object to keep some constants being used in my R code. These are url for remote file, directory for keeping downloaded files, local filenames to be used after downloading, etc. I'm R newbie that is why I decided to use JavaScript-like config object (particularly list) similar to something like this:
var config = {
wd : "/some/working/dir",
zipSrc : "http://www.example.com/remote_data_file.zip",
data_dir : "data",
data_zip : "data.zip",
data_txt : "data.txt",
abs_data_dir : this.wd + this.data_dir,
abs_data_zip : this.abs_data_dir + this.data_zip,
abs_data_txt : this.abs_data_dir + this.data_txt
};
Notice that one can use "this" to reference current object and made some calculation/assignments right inside it.
The most distant place I reached in R is:
config <- list(wd = getwd(),
zipSrc = "http://www.example.com/remote_data_file.zip",
data_dir = "data",
data_zip = "data.zip",
data_txt = "data.txt")
But what if one still needs to calculate abs_data_dir and other similar values? Is it possible to do that job while "building" config list object? Is it possible to derive new named list members based on just created ones like using mutate() in dplyr package? If so is there in R any analogue to JS' "this" to reference current object?
Solution 1
within comes to mind, I came to this after playing with it for a bit:
config = rev(within(list(), {
wd = "/some/working/dir"
zipSrc = "http://www.example.com/remote_data_file.zip"
data_dir = "data"
data_zip = "data.zip"
data_txt = "data.txt"
abs_data_dir = file.path(wd, data_dir)
abs_data_zip = file.path(abs_data_dir, data_zip)
abs_data_txt = file.path(abs_data_dir, data_txt)
}))
config
# $wd
# [1] "/some/working/dir"
# $zipSrc
# [1] "http://www.example.com/remote_data_file.zip"
# $data_dir
# [1] "data"
# $data_zip
# [1] "data.zip"
# $data_txt
# [1] "data.txt"
# $abs_data_dir
# [1] "/some/working/dir/data"
# $abs_data_zip
# [1] "/some/working/dir/data/data.zip"
# $abs_data_txt
# [1] "/some/working/dir/data/data.txt"
You can turn this into a function:
list.eval <- function(...) rev(within(list(), ...))
to be called as follows list.eval({a = 1; b = a}).
Solution 2
Here is another function with a usage closer to list's. It will also handle both named and unnamed arguments like list does:
list.eval <- function(...) {
e <- new.env()
argl <- as.list(sys.call())[-1L]
naml <- names(argl)
.eval.assign <- function(expr, name) {
value <- eval(expr, envir = e)
if (name != "") assign(name, value, envir = e)
return(value)
}
setNames(Map(.eval.assign, argl, naml), naml)
}
z <- 10
list.eval(a = 1, b = z, c = a, 10)
# $a
# [1] 1
#
# $b
# [1] 10
#
# $c
# [1] 1
#
# [[4]]
# [1] 10
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With