a <- 10
f <- function(){
a <<- 3
function() {
a <<- 15
a <- 5
return(a)
}
}
g <- f()
g()
a
When I run the above code I get the following output:
5
15
Can someone please explain how the second output is 15 instead of 3? And the same code returns 10 for a when I do not use "<<-" in the function f.
Just see what your function f returns.
f()
function() {
a <<- 15
a <- 5
return(a)
}
<environment: 0x000000001f1c7898>
So when you assign this result, a function, to g it becomes that function in the output above. The code line a <<- 3 is never executed when you call g.
In other words, the second output is explained in the same fashion the first output is explained, g sets the variable a that exists in the globalenv to 15 and returns a value of variable a <- 5 created in its own environment.
EDIT.
Note that if, like Dason says in his comment, print a before calling g its value has changed to 3 like you expect it in your question. The code line a <<- 3 was indeed executed when f was called.
g <- f() # call 'f'
a # print 'a', the value has changed
[1] 3
g() # now call 'g'
[1] 5
a # and the value of 'a' changed again
[1] 15
Related
I have a problem with a function of the following kind:
fun.name <- function(x,y) {
a<-x
b<-y
for (i in c(a, b)){
i<-i+1
print (i)
}
print(a)
print(b)
}
fun.name(1, 2)
The result is
[1] 2
[1] 3
[1] 1
[1] 2
The same result is obtained if I do not create any a and b and I simply keep x and y ( fun.name <- function(x,y) { for (i in c(a, b))...).
I cannot understand this behavior.
What I wanted was a function which adds one to every arguments and prints the results. Why does not the loop modify the variables a and b when it is defined within the function? I guess it is a problem of environments, and that I have not understood the nature of a function arguments.
Thank you for any suggestions.
I actually expect to see your current output. Here is your code, formatted, with explanations as comments:
fun.name <- function(x,y) {
a <- x
b <- y
for (i in c(a, b)) { # i in (1, 2)
# first iteration: i = 2, print 2
# second iteration: i = 3, print 3
i <- i+1
print(i)
}
print(a) # prints 1 (a was only assigned once)
print(b) # prints 2 (same reason as above)
}
fun.name(1, 2)
There are no changes to a and b after their initial assignments inside the function. But, even if there were changes, the variables a and b would not even be visible outside the scope of the function.
I am new to R. So basically I have 2 questions:
In C++ we can pass objects as references to be able to return multiple modified objects from a function. What is equivalent way to modify multiple objects inside a function? (for example, a and b in fyfunc)
In below code, I thought since I have access to b inside myfunc, I could modify it. But apparently, it's a copy of b. Is there anyway to actually modify b inside myfunc?
a <- c(1,2,3)
b <- c(4,5,6)
myfunc <- function(a) {
b <- b+1
cat(b) # prints: 5 6 7
a <- a+1
}
a <- myfunc(a)
a
b # stil 4 5 6
you can use <<- instead of <- or assign('b', b+1, envir = globalenv()) in function myf.
myf <- function(a) {
assign('b', b+1, envir = globalenv())
cat(b) # prints: 5 6 7
a <- a+1
}
I have a global variable x and want to build a function f that returns the value of x at the time the function is created. Example:
x <- 5
f <- function() return(x)
f()
> 5
x <- 10
f()
> 10 # Should return 5
I want a function that always return 5 (or whatever the value of x is at the time of function creation) without using another global variable. Is that possible?
Still another option using body:
f<-`body<-`(function() {},value=x)
Example:
x<-10
f<-`body<-`(function() {},value=x)
f()
#[1] 10
x<-100
f()
#[1] 10
Digging the source code of body, here is an even cleaner solution equivalent to the above using as.function:
f<-as.function(list(x))
This is not possible with global variables alone. When a function is defined, none of the variables in the function body are actually evaluated till the function is called. What you want seems to be a closure to hold the value at the time of creation. Instead write a function that returns a function
x <- 5
getfun <- function() {z<-x; function() return(z)}
f <- getfun()
x<- 10
g <- getfun()
f()
# [1] 5
g()
# [1] 10
Or even better, don't implicitly use global variables. Create a function that takes a certain set of parameters and returns a new function
returnVal <- function(x) {force(x); function() return(x)}
f<-returnVal(5)
g<-returnVal(10)
f()
# [1] 5
g()
# [1] 10
1) This saves the value of x the first time f is called and then uses that value of x even if x has been changed the next time f is called. Create f in a local environment and have f place x in that environment. If x was not previously there it will now be. If it was previously there then it will be the x retrieved and placed back. The result is that the first x encountered will always be used.
f <- local(function() {
p <- parent.env(environment())
p$x <- x
x
})
x <- 5
f()
## [1] 5
x <- 10
f()
## [1] 5
2) In comments #Konrad and #Frank have suggested the following variation in which we remove the assignment from f and put it in the local.
There is one difference from the viewpoint of the user of the function. This instantiates the value of x at the time the function is defined whereas (1) instantiates x the first time that the function is called and that might be an advantage if you want to separate the definition and the instantiation.
x <- 5
f <- local({ x <- x; function() x })
f()
## [1] 5
x <- 10
f()
## [1] 5
3) We can also consider completely separating the function from the instantiation. This would also allow re-initialization at any time by calling e$init() again.
e <- local({
init <- function() {
p <- parent.env(environment())
p$x <- x
}
run = function() x
environment()
})
x <- 5
e$init()
e$run()
## [1] 5
x <- 10
e$run()
## [1] 5
4) (3) could be implemented using a variety of object oriented frameworks such as Reference Classes, proto or R6. In proto it would be like this:
library(proto)
p <- proto(init = function(.) .$x <- x, run = function(.) x)
x <- 5
p$init()
p$run()
## [1] 5
x <- 10
p$run()
## [1] 5
I would like to create a function that uses a variable already defined such that when I change this variable, the functionality of the created function doesn't change. Normally, when you use create a function in an environment using a variable defined in that said environment, the function will look up the value of the variable in that environment whenever it is called. For example:
> x = 3
> f = function() x + 3
> f()
[1] 6
> x = 4
> f()
[1] 7
I would like to create f such that it is simply the function 3 + 3 and always returns 6. Is there any easy way to do this in R? I know that I could manually assign the relevant parts of the function, i.e.
> body(f)[[2]] = x
> f
function ()
4 + 3
This strategy is quite tedious though, as it requires you to manually go through and change all occurrences. Is there an easier way?
Copy the value to a local variable:
f = local({
x = x
function () x + 3
})
f()
# [1] 6
x = 4
f()
# [1] 3
Now f is defined inside its own environment that contains the cached value of x:
ls(environment(f))
# [1] "x"
environment(f)$x
# [1] 3
I'm new to R (and programming generally), and confused about why the following bits of code yield different results:
x <- 100
for(i in 1:5){
x <- x + 1
print(x)
}
This incrementally prints the sequence 101:105 as I would expect.
x <- 100
f <- function(){
x <- x + 1
print(x)
}
for(i in 1:5){
f()
}
But this just prints 101 five times.
Why does packaging the logic into a function cause it to revert to the original value on each iteration rather than incrementing? And what can I do to make this work as a repeatedly-called function?
The problem
It is because in your function you are dealing with a local variable x on the left side, and a global variable x on the right side. You are not updating the global x in the function, but assigning the value of 101 to the local x. Each time you call the function, the same thing happens, so you assign local x to be 101 5 times, and print it out 5 times.
To help visualize:
# this is the "global" scope
x <- 100
f <- function(){
# Get the "global" x which has value 100,
# add 1 to it, and store it in a new variable x.
x <- x + 1
# The new x has a value of 101
print(x)
}
This would be similar to the following code:
y <- 100
f <- function(){
x <- y + 1
print(x)
}
One possible fix
As for what to do to fix it. Take the variable as the argument, and pass it back as the update. Something like this:
f <- function(old.x) {
new.x <- old.x + 1
print(new.x)
return(new.x)
}
You would want to store the return value, so your updated code would look like:
x <- 100
f <- function(old.x) {
new.x <- old.x + 1
print(new.x)
return(new.x)
}
for (i in 1:5) {
x <- f(x)
}
This does what you want:
f <- function(){
x <<- x + 1
print(x)
}
But you shouldn't do this. Globals are not a good construct. Functions with side-effects cause code to be hard to understand and hard to debug.
A safer way to use a global is to encapsulate it into another environment. Here is an example:
create.f <- function(x) {
return(function() {
x <<- x + 1
print(x)
})
}
f <- create.f(100)
for (i in 1:5) f()
## [1] 101
## [1] 102
## [1] 103
## [1] 104
## [1] 105
Here, the "global" x is in the environment of the body of create.f, where f is defined, and not the global environment. The environment of a function is the environment in which it is defined (and not that in which it is called).