I am writing some functions and I need help figuring out the workings of inner functions in R. I have this test R code:
我正在编写一些函数,我需要帮助找出R中内部函数的工作原理。我有这个测试R代码:
func1 <- function(a, b) {
l <- a * 10
m <- b * 20
func2 <- function() {
n <- l * m
}
func3 <- function() {
o <- n/2
o
}
}
It throws me an error saying R object n is not found when using the following code in the R console:
在R控制台中使用以下代码时,它向我抛出一个错误,指出找不到R对象n:
func1(a=1, b=2)()
Can you help me figure out what I am doing wrong? I assumed when I call a variable within the same function, it should read in.
你能帮我找出我做错了什么吗?我假设当我在同一函数中调用一个变量时,它应该读入。
Also, is function call func1(a=2, b=2) () the only way to call the function? I was thinking func1(a=2, b=2) should work. Any information on why I need to use these extra paranthesis () would be great. Thanks a lot.
另外,函数调用unc1(a=2,b=2)()是调用函数的唯一方式吗?我想函数1(a=2,b=2)应该可以用。任何关于我为什么需要使用这些额外的括号()的信息都将是非常好的。非常感谢。
Note: Please note, that I took a look at this answer, but my question would be an extension of the existing answer. Thank you.
注:请注意,我看了这个答案,但我的问题将是现有答案的扩展。谢谢。
更多回答
func3
doesn't know about n
because it only exists inside func2
函数3不知道n,因为它只存在于函数2中
@DanAdams thank you. Is there a way to pipe n to func3? Thanks.
@DanAdams谢谢你。有没有办法通过管道将n连接到函数3?谢谢。
There are a couple of issues with your example. Here is a brief description and below I've fixed it up to work as I belive you intended:
您的示例中有几个问题。这里是一个简短的描述,下面我已经修复了它,我相信你想要的是:
- It seems as if you may be mixing up the definition of functions with their execution. It's fine to define a function inside a function, but you probably want to also call that function, otherwise it won't do anything.
- As written,
func2
assigns n
which means n
will only exist inside that function. Therefore func3
can't access it. Instead you'll want to make the result of func2
available to func3
by assigning it outside func2
after creating the function.
- Without a
return()
statement, a function will return the last line executed. The last line of the outer function (func1
) is defining func3
. That means the output of calling func1
isn't a value but a function. That's why you need to put the extra parentheses. Instead, you will want to actually call func3
at the end of func1
.
Here's the fixed up version:
以下是修复后的版本:
func1 <- function(a, b) {
l <- a * 10
m <- b * 20
func2 <- function() {
l * m
}
n <- func2()
func3 <- function() {
n/2
}
func3()
}
# demonstrate it works
func1(a = 1, b = 2)
#> [1] 200
Created on 2023-09-10 with reprex v2.0.2
创建于2023-09-10,Reprex v2.0.2
Note, you could also define func2
and func3
separately and then just call them inside func1
. For this to work you will want to define arguments for each rather than relying on accessing variables defined in containing functions by name:
注意,您也可以分别定义函数2和函数3,然后在函数1内部调用它们。为此,您需要为每个函数定义参数,而不是依赖于访问在按名称包含函数中定义的变量:
func2 <- function(l, m) {l * m}
func3 <- function(n) {n/2}
func1 <- function(a, b) {
l <- a * 10
m <- b * 20
n <- func2(l, m)
func3(n)
}
func1(1, 2)
#> [1] 200
Created on 2023-09-10 with reprex v2.0.2
创建于2023-09-10,Reprex v2.0.2
1) If you want func3
to be able to access func2
's variables then define func3
in func2
. Also just defining a function does not cause it to run so run both func2
and func3
.
1)如果希望函数3能够访问函数2的S变量,则在函数2中定义函数3。另外,仅仅定义一个函数并不会导致它运行,所以同时运行函数2和函数3。
The only changes are the ones marked ## plus putting func3
inside func2
.
唯一的更改是标记为##的更改,并将函数3放入函数2中。
func1 <- function(a, b) {
func2 <- function() {
func3 <- function() {
o <- n/2
o
}
n <- l * m
func3() ##
}
l <- a * 10
m <- b * 20
func2() ##
}
func1(a = 1, b = 2)
## [1] 200
2) Another possibility is to have func2
inject n
into func1
. Define e
to be the environment in the running instance of func1
and then just assign n
into e
using e$n
. Since func3
is defined in func1
it has access to func1
's variables. As in (1) we must call func2
and func3
. ## marks the changes.
2)另一种可能是让函数2将n注入函数1。将e定义为函数1的运行实例中的环境,然后使用e$n将n赋给e。由于函数3是在函数1中定义的,因此它可以访问函数1的S变量。如(1)所示,我们必须调用函数2和函数3。##标记更改。
func1 <- function(a, b) {
e <- environment() ##
func2 = function() {
e$n <- l * m ##
func3() ##
}
func3 <- function() {
o <- n/2
o
}
l <- a * 10
m <- b * 20
func2() ##
}
func1(a=1,b=2)
## [1] 200
3) A third approach is to inject func2
's entire body into func1
essentially turning func2
into a macro.
3)第三种方法是将功能2的S全身注入功能1,实质上是将功能2变成宏。
func1 <- function(a, b) {
func2 <- function() eval.parent(substitute({ ##
n <- l * m
func3() ##
})) ##
func3 <- function() {
o <- n/2
o
}
l <- a * 10
m <- b * 20
func2() ##
}
func1(a=1,b=2)
## [1] 200
4) What you are trying to do is essentially using object oriented programming through the back door. We can define func2
and func3
as methods to a proto object p
. The first argument to a proto method is always the object. .$n <-
assigns n
into the proto object and func3
being a method of it can access it.
4)您尝试做的实际上是通过后门使用面向对象编程。我们可以将函数2和函数3定义为原型对象p的方法。原型方法的第一个参数始终是对象。.$n<-将n赋给原型对象,而函数3是它的方法,可以访问它。
library(proto)
func1 <- function(a, b) {
p <- proto(
func2 = function(.) {
.$n <- l * m
.$func3()
},
func3 = function(.) {
o <- n/2
o
}
)
l <- a * 10
m <- b * 20
p$func2()
}
func1(a=1,b=2)
## [1] 200
Update
Have func1
return a number rather than returning a function. Add (2), (3) and (4).
让函数1返回一个数字,而不是返回一个函数。增加第(2)、(3)和(4)项。
If you change the function func2()
to accept l
and m
as
arguments and then func()
to have an agrument n
, you can add calls to func2()
and func3()
at the end of func1()
.
如果将函数Func2()更改为接受L和m作为参数,然后将Func()更改为参数n,则可以在Func1()的末尾添加对Func2()和Func3()的调用。
func1 <- function(a, b) {
l <- a * 10
m <- b * 20
func2 <- function(l, m) {
n <- l * m
}
func3 <- function(n) {
o <- n/2
o
}
func3(func2(l, m))
}
func1(a=1, b=2)
#> [1] 200
更多回答
Thank you for the reply. I see that in func3 you used arguments (l,m). I am looking for a way to use n in funct3. Do you have an approach for writing func3 arguments with only (n)? Thanks.
感谢您的回复。我看到在函数3中您使用了参数(L,m)。我正在寻找一种在函数3中使用n的方法。你有没有一种只用(N)来编写函数3参数的方法?谢谢。
I updated my question to reflect that requirement.
我更新了我的问题以反映这一要求。
我是一名优秀的程序员,十分优秀!