Ahdee
Ahdee

Reputation: 4949

Create a list of functions dynamically with stored variables?

Hi I like to create a list of functions dynamically. The only thing is that I have stored variables that I like to input as my function. For example, say I have a named vector with color.

color = c("blue","red")
names ( color) = c("a","b")

Now I want to create a list of dynamic function returning the color.

c = list()

for ( n in names ( color)){
    c[[n]]= function ( x){
        return ( color[n])
    }
}

however as you can see it returns "color[n]" and not the evaluated value.

> c$a
function ( x){
        return ( color[n])
    }
<bytecode: 0x0000000105e0a108>

Upvotes: 1

Views: 305

Answers (4)

MKR
MKR

Reputation: 1700

EDIT

I have realised based on the above answers that you want to have a function where you then probably want to pass further arguments.

Here is the code with eval(expr())-statement. It's maybe better readable than the above answers, but not really different.

c = list()
for ( n in names (color)){
  c[[n]]= eval(expr(function(x) {return(color[(!!n)])}))
}

Upvotes: 1

MrFlick
MrFlick

Reputation: 206242

Here's one method:

c = list()
for ( n in names ( color)) {
  c[[n]] <- (function(n) {
    force(n)
    function (x) return ( color[n])
  })(n)
}

Note this creates functions as you requested, which means you need to call then with () to get the values returned. For example

c$a()
#      a 
# "blue" 
c$b()
#     b 
# "red" 

Or it's even easier if you replace the for loop withMap`

c <- Map(function(n) {
  function(x) color[n]
}, names(color)) 

c$a()
#      a 
# "blue" 
c$b()
#     b 
# "red" 

Upvotes: 1

Rohit
Rohit

Reputation: 2017

Try something like this:

color = c("blue","red")
names ( color) = c("a","b")

c = list()

for ( n in names ( color)){

  eval(
    parse(
      text = paste0(
        "
c[[n]]= function ( x){
    return ('", color[n],"')
  }"
      )
    )
  )
}
c$a
#> function ( x){
#>     return ('blue')
#>   }

Created on 2020-03-04 by the reprex package (v0.3.0)

Upvotes: 1

Weihuang Wong
Weihuang Wong

Reputation: 13118

This answer uses the eval(parse(…)) construct, which has its flaws (What specifically are the dangers of eval(parse(...))?). But you could try:

for (n in names(color)) {
  c[[n]] <- eval(parse(text = sprintf("function(x) return(color['%s'])", n)))
}

c
# $`a`
# function (x) 
# return(color["a"])

# $b
# function (x) 
# return(color["b"])

c$a()
#      a 
# "blue" 

But as commenters (to your question, and elsewhere on SO) have suggested, there may be more elegant solutions to your problem, depending on your context and use case.

Upvotes: 2

Related Questions