Reputation: 145
Suppose you define a function in R using the following code:
a <- 1
f <- function(x) x + a
If you latter redefine a
you will change the function f. (So, f(1) = 2
as given but if you latter on redefine a =2
then f(1) = 3
. Is there a way to force R to use the value of a
at the time it compiles the function? (That is, f
would not change with latter redefinitions of a
).
The above is the shortest case I could thought of that embodies the problem I am having. More specifically, as requested, my situation is:
I am working with a bunch of objects I am calling "person". Each person is defined as a probability distribution that depends on a n dimensional vector $a$ and a n dimensional vector of constrains w (the share of wealth).
I want to create a "society" with N people, that is a list of N persons. To that end, I created two n by N matrices A and W. I now loop over 1 to N to create the individuals.
Society <- list()
### doesn't evaluate theta at the time, but does w...
for (i in 1:Npeople) {
w <- WealthDist[i,]
u <- function(x) prod(x^A[i,])
P <- list(u,w)
names(P) <- c("objective","w")
Society[[length(Society)+1]] <- P
}
w gets is pass-by-value, so each person gets the right amount of wealth. But A is pass-by-reference -- everybody is being assigned the same function u (namely, the function using i = N)
To finish it up, the next steps are to get the Society and, via two optimizations get an "equilibrium point".
Upvotes: 1
Views: 3719
Reputation:
You can create a function which uses a locked binding and creates a function to complete your purpose. The former value of a will be used for w
which will be stored in the environment of the function and will not be replaced by further values changes of a
.
a <- 1
j <- new.env() # create a new environment
create.func <- function () {
j$w <<- a
function (x) {
x+ j$w
}
}
f <- create.func()
a <- 2
f(2)
[1] 3 # if w was changed this should be 4
Credits to Andrew Taylor (see comments)
EDIT: BE CAREFUL: f will change if you call create.func
, even if you do not store it into f. To avoid this, you could write this code (it clearly depends on what you want).
a <- 1
create.func <- function (x) {
j <- new.env()
j$w <- a
function (x) {
x + j$w
}
}
f <- create.func()
f(1)
[1] 2
a <- 2
q <- create.func()
q(1)
[1] 3
f(1)
[1] 2
EDIT 2: Lazy evaluation doesn't apply here because a is evaluated by being set to j$w
. If you had used it as an argument say:
function(a)
function(x)
#use a here
you would have to use force
before defining the second function, because then it wouldn't be evaluated.
EDIT 3: I removed the foo <-
etc. The function will return as soon as it is declared, since you want it to be similar to the code factories defined in your link.
EDIT by OPJust to add to the accepted answer that in spirit of Function Factory in R the code below works:
funs.gen <- function(n) {
force(n)
function(x) {
x + n
}
}
funs = list()
for (i in seq(length(names))) {
n = names[i]
funs[[n]] = funs.gen(i)
}
Upvotes: 4
Reputation: 5586
R doesn't do pass by reference; everything is passed to functions by value. As you've noticed, since a
is defined in the global environment, functions which reference a
are referencing the global value of a
, which is subject to change. To ensure that a specific value of a
is used, you can use it as a parameter in the function.
f <- function(x, a = 1) {
x + a
}
This defines a
as a parameter that defaults to 1. The value of a
used by the function will then always be the value passed to the function, regardless of whether a
is defined in the global environment.
If you're going to use lapply()
, you simply pass a
as a parameter to lapply()
.
lapply(X, f, a = <value>)
Upvotes: 2