Reputation: 331
I'd like to create a few functions that do slightly different things and that can each accept a global variable.
I use assign
to assign the function this_value
to the name it should have, this_key
. The three functions it should create are func_a
, func_b
, and func_c
.
Each newly minted function should be able to take an input x
and do something particular to that function to x
; in this case, print "key_name: name
----- value_x: x
". So name
should depend on whether the function is func_a
, func_b
, or func_c
; e.g., calling func_a
should give us "key_name: a".
to_name <- c("a", "b", "c")
create_funcs <- function() {
all_funcs <- list()
for (name in to_name) {
this_key <- paste0("func_", name)
this_value <<- function(x) {
paste0("key_name: ", name, " ----- value_x: ", x)
}
assign(this_key, this_value, envir = .GlobalEnv)
all_funcs <- c(all_funcs, this_key)
}
return(all_funcs)
}
create_funcs()
However, after creating the functions, they each only return a name
of "c", or the last value in the vector to_name
.
func_a("foo") # key_name: c ----- value_x: foo
func_b("bar") # key_name: c ----- value_x: bar
Instead, func_a("foo")
should return "key_name: a ----- value_x: foo".
For what it's worth, this works in a similar object-assigning function:
create_objects <- function() {
all_objs <- list()
for (name in to_name) {
this_key <- paste0("key_", name)
this_value <- paste0("value_", name)
assign(this_key, this_value, envir = .GlobalEnv)
all_objs <- c(all_objs, this_key)
}
return(all_objs)
}
create_objects()
Example:
key_a # value_a
Thanks for taking a look!
Upvotes: 1
Views: 1531
Reputation: 3017
I'm not entirely sure if this solves your problem, since your real use case is probably more complicated than this reproducible example. But you might want to check out purrr::partial
.
Here's a possible solution I came up with using that function.
library(purrr)
func_ <- function(x, key_name) {
paste0("key_name: ", key_name, " ----- value_x: ", x)
}
func_a <- partial(func_, key_name = "a")
func_a("foo")
#> [1] "key_name: a ----- value_x: foo"
assign("func_b", partial(func_, key_name = "b"))
func_b("foo")
#> [1] "key_name: b ----- value_x: foo"
EDIT:
Here you can just take and character vector and iterate over each element (like with a for loop) using purrr::walk
to create a new function for each one. You just have to make sure to set the environment to .GlobalEnv
in the assign()
call. I don't know that much about environment scoping for things like this, and feel like I've read that this can sometimes be a bad idea, but it seems to do what you described. Hope this helps.
letters %>% walk(~ assign(x = paste0("func_", .x),
value = partial(func_, key_name = .x),
envir = .GlobalEnv))
func_x("foo")
#> [1] "key_name: x ----- value_x: foo"
Upvotes: 1