Reputation: 1111
I have 3 vectors of equal length y
, h
and hp
defined as follows:
y <- c(2, 5, 6)
h <- c(4, 25, 35)
hp <- c(3, 10, 12)
The values are simply illustrative.
I want to create an output list final_list
of functions in x
as follows
function(x) y + (h - hp) * x
(only ideal illustrative output shown):
[[1]]
[1] function(x) 2 + (1) * x
[[2]]
[1] function(x) 5 + (15) * x
[[3]]
[1] function(x) 6 + (23) * x
I am aware that this can be done with eval/parse, but this does not produce transparent output for the functions.
I would like to create the functions from these 3 vectors and output without using eval/parse. If this is possible I would be really happy to learn and be impressed!
Upvotes: 5
Views: 145
Reputation: 263352
Just using the function
-function will succeed if it is executed in the correct environment.
> mapply( function(y,h,hp) function(x){ y+(h-hp)*x }, y,h,hp)
[[1]]
function (x)
{
y + (h - hp) * x
}
<environment: 0x7fb570828710>
[[2]]
function (x)
{
y + (h - hp) * x
}
<environment: 0x7fb570823718>
[[3]]
function (x)
{
y + (h - hp) * x
}
<environment: 0x7fb57081b5c8>
> myfuns[[1]](x=1:10)
[1] 3 4 5 6 7 8 9 10 11 12
> 2+(h[1]-hp[1])*1:10
[1] 3 4 5 6 7 8 9 10 11 12
> myfuns[[2]](x=1:10)
[1] 20 35 50 65 80 95 110 125 140 155
Each of those function definitions (actually closures) carries along the first matching values that existed at the time of its creation when the interpreted traveled along the search path.
> environment(myfuns[[1]])[["y"]]
[1] 2
> environment(myfuns[[1]])[["h"]]
[1] 4
> environment(myfuns[[1]])[["hp"]]
[1] 3
Upvotes: 3
Reputation: 99331
You can use Map()
with substitute()
. The middle expressions are not yet evaluated, but I don't think that's such a big deal. They will be evaluated when the functions are called. Basically we just assemble the function in parts.
funs <- Map(
function(a, b, c) {
f <- function(x) x
body(f) <- substitute(y + (h - hp) * x, list(y = a, h = b, hp = c))
f
},
a = y, b = h, c = hp
)
funs
# [[1]]
# function (x)
# 2 + (4 - 3) * x
# <environment: 0x4543fd0>
#
# [[2]]
# function (x)
# 5 + (25 - 10) * x
# <environment: 0x4549e20>
#
# [[3]]
# function (x)
# 6 + (35 - 12) * x
# <environment: 0x454e5d8>
Now let's call the functions -
sapply(funs, function(a) a(1))
# [1] 3 20 29
Note: If you really need those middle expressions evaluated in the function bodies, you can use the following instead.
make <- function(a, b, c) {
d <- b - c
f <- function(x) x
body(f) <- substitute(y + (e) * x, list(y = a, e = d))
f
}
funs <- Map(make, y, h, hp)
Upvotes: 5
Reputation: 61933
y <- c(2,5,6)
h <- c(4, 25, 35)
hp <- c(3, 10, 12)
fun_create <- function(y, h, hp){
fun <- function(x){y + (h - hp)*x}
return(fun)
}
out <- mapply(y, h, hp, FUN = fun_create)
The output doesn't give what you might expect but it works correctly:
> out
[[1]]
function (x)
{
y + (h - hp) * x
}
<environment: 0x282ee40>
[[2]]
function (x)
{
y + (h - hp) * x
}
<environment: 0x282e610>
[[3]]
function (x)
{
y + (h - hp) * x
}
<environment: 0x282dde0>
> out[[1]](1)
[1] 3
Upvotes: 5