Suppose I have a closure add_y(y)
which returns a function that adds y
to its input.
add_y <- function(y) {
function(x) {
x y
}
}
add_4 <- add_y(4)
So the value of add_4
is a function that adds 4 to its input. This works. I would like to be use dput
to show the definition of add_4
as
function(x) {
x 4
}
but this is not what dput returns.
add_y <- function(y) {
function(x) {
x y
}
}
add_4 <- add_y(4)
dput(add_4)
#> function (x)
#> {
#> x y
#> }
Is there a way to obtain source code that would run outside of the enclosing environment?
CodePudding user response:
This can work but it involves changing the contents of add_y
.
library(rlang)
library(magrittr)
library(stringr)
add_y <- function(y) {
fn <- expr(function(x) {
x !!y
})
fn <- deparse(fn) %>% str_c(collapse = "")
fn <- eval(parse(text = fn))
}
add_4 <- add_y(4)
dput(add_4)
#> function (x)
#> {
#> x 4
#> }
Created on 2021-12-24 by the reprex package (v2.0.1)
CodePudding user response:
You could construct a dput
replacement that generated code that creates a function like add_4
, but it wouldn't deparse the way you want:
dput_with_env <- function(f) {
fn <- deparse(f, control = c("keepNA", "keepInteger",
"niceNames", "showAttributes"))
env <- as.list(environment(f))
cat("local({ f =\n")
cat(fn, sep = "\n")
cat("\nenvironment(f) <- list2env(\n")
dput(env)
cat(")\nf})")
}
add_y <- function(y) {
function(x) {
x y
}
}
add_4 <- add_y(4)
dput_with_env(add_4)
#> local({ f =
#> function (x)
#> {
#> x y
#> }
#>
#> environment(f) <- list2env(
#> list(y = 4)
#> )
#> f})
Created on 2021-12-24 by the reprex package (v2.0.1)
This assumes that the environment of add_4
is quite simple, so the parent of its environment can be the environment in place when you evaluate the code. We can try it out:
newfn <- local({ f =
function (x)
{
x y
}
environment(f) <- list2env(
list(y = 4)
)
f})
newfn
#> function (x)
#> {
#> x y
#> }
#> <environment: 0x7f9a1b5e2318>
newfn(1)
#> [1] 5
Created on 2021-12-24 by the reprex package (v2.0.1)
CodePudding user response:
Not with a dput()
, no. The dput()
function will not create text representations of environments.
If you want to save the function, you could do
save(add_4, file="add4.Rdata")
and then in another R session
load("add4.Rdata")
That will capture all the enclosed values and your function will behave as it did before