I'm learning R programming. I'm unable to understand how function within function works in R. Example:
f <- function(y) {
function() { y }
}
f()
f(2)()
I'm not able to understand why $f() is not working and showing following message:
function() { y }
<environment: 0x0000000015e8d470>
but when I use $f(4)() then it is showing answer as 4.
Please explain your answer in brief so that I can understand it easily.
For a more general case, let's change the "inner" function a little bit:
f <- function(y) {
function(x) { y + x}
}
Now f(2) returns a function that adds 2 to its argument. The value 2 is kept in the function's environment:
> f(2)
function(x) { y + x}
<environment: 0x0000000015a690f0>
> environment(f(2))$y
[1] 2
.. and you can change it if you really want to but for this you need to assign a name to the output of f():
> g <- f(2)
> environment(g)$y
[1] 2
> environment(g)$y <- 3
> g(1)
[1] 4
Why do you need a g here? Because otherwise, the environment created with f(2) is garbage collected immediately, so there's no way to access it:
> environment(f(2))$y<-4
Error in environment(f(2))$y <- 4 :
target of assignment expands to non-language object
This won't affect the case when you use, say, f(2) only once:
> f(2)(3)
[1] 5
The reason is that the inner function behave as the answer of the outer one son by just doing f(), the result is a function. The best way is to call it double f(3)() as the inner function doesn't take any argument.
Related
I'm studying R environments but I have got a question reading the "Advanced R" book by Hadley Wickham. Is it possible to make the execution environment of a function permanent?
I will try to explain the why of my question.
When Wickham explains how the execution environment of a function works the following example is shown:
j <- function() {
if (!exists("a")) {
a <- 1
} else {
a <- a + 1
}
print(a)
}
j()
I have understood why every time the function j gets called the returned value is 1.
In another part of the text he says:
When you create a function inside another function, the enclosing
environment of the child function is the execution environment of the
parent, and the execution environment is no longer ephemeral.
So I have thought to create the following function:
j <- function() {
if (!exists("a")) {
a <- 1
} else {
a <- a + 1
}
print(a)
g <- function() {}
g()
}
j()
But the returned value is always 1, so I suppose it's because the execution environment continues to be destroyed every time. What does that "no longer ephemeral" mean?
Based on the book there is also possible to use function factory structure (a function that creates another function) to capture the ephemeral execution environment of the first function. The following example is just a simple way of how we could capture it:
library(rlang)
j <- function() {
print(current_env())
a <- 1
k <- function() {
if (!exists("a")) {
a <- 1
} else {
a <- a + 1
}
print(a)
}
}
plus <- j()
> plus <- j()
<environment: 0x000001ca98bc1598>
Now no matter how many times you use the function plus, its environment will always be the then execution environment of the first function:
library(rlang)
env_print(plus)
<environment: 000001CA98BC1598>
parent: <environment: global>
bindings:
* k: <fn>
* a: <dbl>
plus()
[1] 2
env_print(plus)
<environment: 000001CA98BC1598>
parent: <environment: global>
bindings:
* k: <fn>
* a: <dbl>
I hope this to some extent answered your question, however there might be better answers out there too.
A permanent environment within a function is called a "closure". Here a toy example to demonstrate this. Check it out and then modify your code accordingly.
closure <- function(j) {
i <- 1
function(x) {
i <<- i + 1
j * i + x
}
}
i <- 12345
instance <- closure(11)
instance(3)
#[1] 25
instance(3)
#[1] 36
instance(3)
#[1] 47
otherObj <- closure(2)
otherObj(3)
#[1] 7
instance(2)
#[1] 57
I came across this example in Advanced R by Hadley. My question is after defining the function, j(1) outputs the inner function definition as supposed to what j(1)() is outputting? Intuitively, I think j(1) should output [1] 1 2
Could anyone explain what's going on actually? What's the difference between j(1) and j(1)() ?
> j <- function(x) {
+ y <- 2
+ function() {
+ c(x,y)
+ }
+ }
> k <- j(1)
> k()
[1] 1 2
> j(1)
function() {
c(x,y)
}
<environment: 0x7fa184353bf8>
> j()
function() {
c(x,y)
}
<environment: 0x7fa18b5ad0d0>
> j(1)()
[1] 1 2
tl;dr In R, the return value of a function can also be a function. That's the case here. j(1) returns a function, whereas j(1)() returns a numeric vector.
The difference between j(1) and j(1)() is that j(1) outputs a function because that's the last value in the definition of j. Functions return their last expression (or the value found in a relevant return() call), which in this case is also a function. j(1)() is calling the last value of j, which is the function returned from it. It does not take an argument, so the empty parentheses () is the argument list for j(1)
It might become a bit more clear if we have a closer look at j and some of its properties.
j <- function(x) {
y <- 2
function() {
c(x, y)
}
}
The difference between the calls becomes quite apparent when we look at their classes.
class(j(1))
# [1] "function"
class(j(1)())
# [1] "numeric"
When you defined j, 2 is hard-coded into its return function as the second value of the vector returned from that function. We can see the precise return value of a call to j(1) with
library(pryr)
unenclose(j(1))
# function ()
# {
# c(1, 2)
# }
So a call to j(1)() (or k()) will deliver the vector c(1, 2). Similarly, if we call j(5), the return value of j(5)() is c(5, 2)
unenclose(j(5))
# function ()
# {
# c(5, 2)
# }
Hope that helps.
Credit to #Khashaa for mentioning the unenclose() function (comment deleted).
Why does
f <- function(a) {
g <- function(a=a) {
return(a + 2)
}
return(g())
}
f(3) # Error in a + 2: 'a' is missing
cause an error? It has something to do with the a=a argument, particularly with the fact that the variable names are the same. What exactly is going on?
Here are some similar pieces of code that work as expected:
f <- function(a) {
g <- function(a) {
return(a + 2)
}
return(g(a))
}
f(3) # 5
f <- function(a) {
g <- function(g_a=a) {
return(g_a + 2)
}
return(g())
}
f(3) # 5
g <- function(a) a + 2
f <- function(a) g(a)
f(3) # 5
The problem is that, as explained in the R language definition:
The default arguments to a function are evaluated in the evaluation frame of the function.
In your first code block, when you call g() without any arguments, it falls back on its default value of a, which is a. Evaluating that in the "frame of the function" (i.e. the environment created by the call to g()), it finds an argument whose name matches the symbol a, and its value is a. When it looks for the value of that a, it finds an argument whose name matches that symbol, and whose value is a. When...
As you can see, you're stuck in a loop, which is what the error message is trying to tell you:
Error in g() :
promise already under evaluation: recursive default argument reference or
earlier problems?
Your second attempt, which calls g(a) works as you expected, because you've supplied an argument, and, as explained in the same section of R-lang:
The supplied arguments to a function are evaluated in the evaluation frame of the calling function.
There it finds a symbol a, which is bound to whatever value you passed in to the outer function's formal argument a, and all is well.
The problem is the a=a part. An argument can't be its own default. That is a circular reference.
This example may help clarify how it works:
x <- 1
f <- function(a = x) { x <- 2; a }
f()
## [1] 2
Note that a does not have the default 1; it has the default 2. It looks first in the function itself for the default. In a similar way a=a would cause a to be its own default which is circular.
I recently learned that R has both lexical and dynamical scoping available, but that it uses lexical scope by default. The next case really confused me:
> x <- 1
> f <- function(y) { x + y }
> f(5) # we expect 6
[1] 6
> x <- 10
> f(5) # shouldn't we again expect 6?
[1] 15
Shouldn't f be evaluated using the environment where (and at the time!) it was defined and not where it was called ? How is this lexical scope? Thanks!
f <- function(y) { x + y }
was defined in the global environment and so for the parts not defined in the function itself (i.e.x), R looks to the global environment for them.
a=1
b=2
f<-function(x)
{
a*x + b
}
g<-function(x)
{
a=2
b=1
f(x)
}
# compare f(2) and g(2)
This example above is from here and gives a good discussion. Main point being, f() within g() ignores the definitions of a and b in g().
From the wiki on "Scope"
In object-oriented programming, dynamic dispatch selects an object method at runtime, though whether the actual name binding is done at compile time or run time depends on the language.
In R, when I do
substitute(function(a) { a })[[2]]
I see the following pairlist:
$a
Note that the value of the element is empty. How can I create such a pairlist? The following doesn't work for me :
> pairlist(a="")
$a
[1] ""
I am asking this in the context of programmatically creating a function. I want to do something like
> call("function", pairlist(a=""), call("{", as.symbol("a")))
function(a = "") {
a
}
This is quite close to what I get by doing
> substitute(function(a){a})
function(a) {
a
}
except for the function argument part.
try this:
> as.pairlist(alist(a=))
$a
maybe what you want to do is:
> f2 <- as.function(alist(a=1,b=,{a+b}))
> f2
function (a = 1, b)
{
a + b
}
With alist(a=).
You may also find the functions formals and body helpful in programatically creating a function, rather than substitute and call. Here's an example from the documentation ?formals
f <- function(x) a+b
formals(f) <- alist(a=,b=3) # function(a,b=3)a+b
f(2) # result = 5
which could be extended like this
body(f) <- expression(2*a+b)
f(2) # result = 7