Creating R function with local variable using its value - r

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

Related

Is there any way to return all objects defined in a function in R?

Is there any way to return all objects defined in a function in R?
Here's a little example of what I'm trying to do. I want to return everything I've assigned a value to inside this function (dave, mark, xx, z (if exists)). The print statement is superfluous.
I normally wouldn't even try to do this, it's just I'm converting a sourced file into a function, and previously all objects were sourced into the global environment, which is what I still need, and I'd rather not create an enormous list of all the objects at the end of the function.
Ideally, after running the function, all the objects are in the global environment and can be accessed from the list. (Automatically delisting and leaving them as standalone objects would be great.) Perhaps this should be a class?
It errors out if any of these are NULL, if for example, y is supplied as NULL in the function definition arguments (i.e. test_func <- function(x = c(1, 2), y = NULL) ...).
test_func <- function(x = c(1, 2), y = 3) {
xx <- x * x
if(!is.null(y)) z <- x * y
mark <- "hello"
dave <- data.frame(x = x, xx = xx)
whatshere <- ls()
print(whatshere)
whatsout <- list()
for (i in 1:length(whatshere)) {
whatsout[[i]] <- get(whatshere[[i]])
}
names(whatsout) <- whatshere
return(whatsout)
}
test_func()
#> [1] "dave" "mark" "x" "xx" "y" "z"
#> $dave
#> x xx
#> 1 1 1
#> 2 2 4
#>
#> $mark
#> [1] "hello"
#>
#> $x
#> [1] 1 2
#>
#> $xx
#> [1] 1 4
#>
#> $y
#> [1] 3
#>
#> $z
#> [1] 3 6
Created on 2020-03-03 by the reprex package (v0.3.0)
Is there any way to return all objects defined in a function in R?
Literally, there is1:
as.list(environment())
However, I’d generally recommend against this: be explicit, name all objects that you want to return individually:
list(
foo = foo,
bar = bar,
…
)
1 This will include arguments, since these are just locally defined values. To exclude formal arguments, do this:
values = as.list(environment())
values[setdiff(names(values), names(formals()))]

How to return multiple objects and only show part of the return when we call the function

For user defined function, I use list if there are multiple objects to return.
However, not all information are equal important.
For example, I am writing a function which estimates for 3 parameters by iteration. The final converged result is the most important, so I would like to see 3 numbers after I call my function. While the history of iteration (all steps of estimation) sometimes is needed, but printing out all steps all the time occupies the whole screen.
Currently, I use list to return 3 matrices, which contains all steps.
Is there a way that make the function return the same thing, but when I call the function, it only show the last 3 converged estimates. And if I need the estimation step, then I use $ to get them. So it looks like:
MyEstimate(arg1, arg2, ...) # only show 3 final estimates
model <- MyEstimate(arg1, arg2, ...)
model$theta1 # show all steps of estimates of theta1
Basically, I want it works like 'lm' function:
Show something important, like estimates of parameters;
Don't show, but still can access if we want, like the design matrix X
I reckon there is no simple answer for that.
To achieved this, what should I learn?
You can use print to always print the values you are interested in when you call the function, while maintain all information in the returned object.
> myFun <- function(){
a <- sample(1:10, 10, TRUE)
b <- sample(1:10, 10, TRUE)
c <- sample(1:10, 10, TRUE)
# Print Last value
print(tail(a,1))
print(tail(b,1))
print(tail(c,1))
return(list(a = a, b=b, c=c))
}
> Obj <- myFun()
[1] 10
[1] 5
[1] 2
> Obj
$a
[1] 2 9 4 7 3 2 2 5 1 10
$b
[1] 6 4 9 8 8 9 2 8 6 5
$c
[1] 2 6 9 2 6 7 8 2 6 2
You can use the S3 classes mechanism to have your function MyEstimate return an object of a special class, made up by you, and write a print method for that class. You would subclass class "list".
If this special class is named "tautology" you would write method print.tautology. Something along the lines of the following:
print.tautology <- function(x){
h <- tail(x[[1]], 3)
print(h)
invisible(h)
}
MyEstimate <- function(x, y, ...){
res <- list(theta1 = 1:10, beta2 = 11:15)
class(res) <- c("tautology", class(res))
res
}
arg1 <- 1
arg2 <- 2
MyEstimate(arg1, arg2) # only show 3 final estimates
#[1] 8 9 10
model <- MyEstimate(arg1, arg2)
model$theta1 # show all steps of estimates of theta1
#[1] 1 2 3 4 5 6 7 8 9 10

Equivalent to let expressions in r

Is there some equivalent to express let expressions in r? As an example take this simple haskell code:
let x = 1 in x + 1
Many thanks in advance.
One equivalent would be a lambda function, which you can define and call in a single statement:
(function(x) x+1)(x = 1)
The first () part defines a function, while the second () part calls that function, supplying the value of 1 for the argument named x.
Here are a few:
x <- 100
# 1
with(list(x = 1), x + 1)
## [1] 2
# 2
local(x + 1, list(x = 1))
## [1] 2
# 2a
local({
x <- 1
x + 1
})
## [1] 2
# 3
eval(substitute(x + 1, list(x = 1)))
## [1] 2
# 4
library(wrapr)
let(c(x = "1"),
x + 1,
subsMethod = "stringsubs",
strict = FALSE)
## [1] 2
x
## [1] 100
Also there is an open issue in the lambda.r package to add let.
If the intent of this is to make x only available in that expression, environments could offer this capability:
#make an environment
myenv <- new.env()
#assign 1 to variable x in our environment
myenv$x <- 1
#evaluate the expression within our environment
with(myenv, x + 1)
#[1] 2
#x only works within our created environment and not on the global environment
#(i.e. the default environment when working on the console)
x + 1
#Error: object 'x' not found
As per #Roland 's comment this can be shortened to local({x <- 1; x + 1}). See ?local.
One equivalent is a lambda function, whereby, you use the
implicit local({ }) within the function body
(this is a slightly improved answer of #ArtemSokolov's answer).
(function() {
x <- 1
x + 1
})()
This is equivalent to
local({
x <- 1
x + 1
})

How does scoping work in R?

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

Using current value of global variable in function definition

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

Resources