I have a function say,
inc <- function(t) {
f <- 1
t + f
}
So, for the first time function inc gets called, f will be 1, but the next time it gets called f value should be 2 and when the function inc gets called for the 3rd time f value should be 3 and so on...
How do I do it in R?
I usually use this. I don't know if it is a trick or an hack:
getF <- function(){
x <- 1
function(t){
x <<- t + x
}
}
f <- getF()
f is a function (the return value of getF) and it's enclosing environment is not the global environment, but the environment wherein f was defined. Look at environment(f). <<- assigns x into that environment: see ls(environment(f)) and get("x", environment(f)).
print(f(3))#4
print(f(4))#8
This might be easier to understand, but creates an environment in the workspace as a side effect:
inc <- function(t) {
if (!exists("e")) {
e <<- new.env()
e$x <- 1
}
e$x <- e$x + t
e$x
}
inc(2)
#[1] 3
inc(2)
#[1] 5
Related
I have written a function in R like this:
foo <- function(a, b = 1) {
...
}
But now I want to change the default argument b, like:
foo(b = 2)
This is a function of a in principle. But R doesn't allow this, which throws me an error.
How can I fix it?
Your code in foo(b = 2) is function application: if everything works as expected, it will give you a value rather than a function.
You can modify the default values of arguments using formals:
foo <- function(a, b = 1) {
a + b
}
formals(foo)$b <- 2
foo
#function (a, b = 2)
# {
# a + b
# }
If you don't want to modify your foo directly, there are several options:
1) Copy first, change later
foa <- foo
formals(foa)$b <- 42
One might think of using "formals<-" as a shortcut but that can be complicated as you need to supply the full list of arguments (using alist rather than list because the former can take an empty argument):
"formals<-"(foo, , list(b=2)) # trying it with `list`
function (b = 2) # we lost one argument!
{
a + b
}
"formals<-"(foo, , alist(a=, b=42)) # this one is better!
function (a, b = 42)
{
a + b
}
2) Use purr::partial or function(a) foo(a,b=42) as recommended in the other answer.
3) And a third way ... one can actually write a very simple function (I'll call it p2) that changes some of the default arguments of a function and returns the changed function:
p2 <- function(f, l){
formals(f)[names(l)] <- l
f
}
p2(foo, list(b=42)) # changing a default: function (a, b = 42) a+b
p2(foo, alist(b=)) # removing a default: function (a, b) a+b
p2(foo, list(c="bingo") # adding an argument: function (a, b = 2, c = "bingo") a+b
A modified version:
p3 <- function(f, ...){
l <- as.list(sys.call())[-(1L:2L)] # code from `alist`
formals(f)[names(l)] <- l
f
}
Now the usage becomes shorter:
p3(foo, b=43) # function (a, b = 43) a+b
p3(foo, b=) # function(a,b) a+b
Note that p2 and p3 won't work properly with generic functions such as mean and min. This is probably the reason why the code in purrr:partial is so much more complicated.
You can call foo as so: foo(a, b = whatever)
If you need to change the default b to the same value really often, you could make a new foo-related function.
You could either define a new function:
# partially substitute in a `b` value
goo <- purrr::partial(foo, b = 2, .first = FALSE)
# or, a bit more explicitly,
hoo <- function(a) {foo(a, b = 2)}
or construct a function builder/factory, that allows you to build as many foo-related functions as you like
foo_builder <- function(b = 1) {
function(a) {
# your definition of foo goes here
blah <- blah_f(a, b)
}
}
Now you can pass in a b value to foo_builder and it will return the equivalent function to foo(a, b = whatever_you_passed_to_foo_builder)
goo <- foo_builder(2)
goo(a = ...)
For example,
foo_builder <- function(b = 1){
function(a){
message(b)
a + b
}
}
Now when the internal function is defined by foo_builder, it takes the value of b that is available to the foo_builder environment. This is 1 by default, but can be changed.
For example,
# default
foo_builder()(1)
1
[1] 2
# with b=2 in the closure returned by foo_builder
b <- 2
fb <- foo_builder(b)
fb(1)
2
[1] 3
A commenter suggested that you ought to force the evaluation of b when you make closures this way; because of the following:
b <- 2
fb <- foo_builder(b)
b <- 3
fb(1)
# 3
# [1] 4
So maybe rewrite the foo_builder:
foo_builder <- function(b = 1){
force(b)
function(a){
message(b)
a + b
}
}
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
Suppose I have a function called l:
l <- function(x) x + 1
then define another function, m, but within m, redefine l:
m <- function() {
l <- function(x) x*2
l(10)
}
m()
Why does m return x*2, and not x+1?
If you're not sure what's going on, it can be helpful to add some print statements. Let's add a few print statements to your code -- one before m is called, two inside the m function, and one after m is called:
l <- function(x) x + 1
m <- function() {
print(l)
l <- function(x) x * 2
print(l)
l(10)
}
print(l)
# function(x) x + 1
m()
# function(x) x + 1
# function(x) x * 2
# <environment: 0x7f8da5ac3b58>
# [1] 20
print(l)
# function(x) x + 1
Before m is called and at the top of m, l is defined as a function that returns x+1. However, within m you change l to be a new function, one that returns x*2, as indicated by the second print statement in that function. As a result, calling l(10) returns 20. Finally once you leave that function you are back to the original l definition (x+1) because the x*2 version was only defined for the function. The concept of a function only being defined locally is called name masking.
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).
How can I construct a function using the current value of a variable?
Here is an example:
x <- 2
f <- function() { return(x) }
x <- 3
f() # evaluates to 3 as expected, but I'd like it to evaluate to 2.
This is where R's lexical scoping comes in handy:
MakeF <- function() {
x <- x
f <- function() {
return(x)
}
return(f)
}
x <- 2
f <- MakeF()
x <- 3
Which gives:
> f()
[1] 2