我还是R的新手,还在理解懒惰的评价。我在SO(R functions that pass on unevaluated arguments to other functions)上阅读了不少主题,但我仍然不确定。
问题1:
这是我的代码:
f <- function(x = ls()) {
a<-1
#x ##without x
}
f(x=ls())
当我执行此代码即f()
时,没有任何内容返回。具体来说,我没有看到a
的价值。为什么会这样?
问题2:
此外,我确实在此代码中看到a
的值:
f <- function(x = ls()) {
a<-1
x ##with x
}
f(x=ls())
当我按f()
执行该功能时,我得到:
[1] "a" "x"
为什么会这样?有人可以帮助我吗?
答案 0 :(得分:3)
问题1
这与懒惰评估无关。
函数返回它执行的最后一个语句的结果。在这种情况下,最后一个语句是a <- 1
。 a <- 1
的结果是一个。例如,您可以执行b <- a <- 1
,这会导致b
等于1.因此,在这种情况下,函数返回1.
> f <- function(x = ls()) {
+ a<-1
+ }
> b <- f(x=ls())
> print(b)
[1] 1
论证x
没有使用,所以没有任何作用。
函数可以明显地返回值(默认值)或不可见。为了无形地返回,可以使用函数invisible
。一个例子:
> f1 <- function() {
+ 1
+ }
> f1()
[1] 1
>
> f2 <- function() {
+ invisible(1)
+ }
> f2()
>
在这种情况下,f2
似乎没有返回任何内容。但是,它仍然返回值1.隐藏的内容不会在调用函数时打印任何内容,并且结果未分配给任何内容。与您的示例的相关性是a <- 1
也无形地返回。这就是你的功能似乎没有返回任何东西的原因。但是,当分配到上面的b
时,b
仍会获得值1.
问题2
首先,我会解释为什么你会看到你看到的结果。您在结果中看到的a
是以前的代码造成的。如果我们首先清理工作区,我们只会看到f
。这是有道理的,因为我们创建变量f
(函数也是R中的变量),然后执行ls()
。
> rm(list = ls())
>
> f <- function(x = ls()) {
+ a<-1
+ x
+ }
> f(x=ls())
[1] "f"
该函数的作用(至少是您期望的),如果首先列出所有变量ls()
,然后将结果作为x
传递给函数。然后,此函数返回x
,这是所有变量的列表,然后打印出来。
如何修改此功能以显示工作中的惰性评估
> rm(list = ls())
>
> f <- function(x) {
+ a <<- 1
+ x
+ }
>
> f(x = ls())
[1] "a" "f"
>
在这种情况下,使用全局赋值(a <<- 1
),它在全局工作空间中创建一个新变量a
(不是您通常想要做的事情)。
在这种情况下,人们仍然希望函数调用的结果只是f
。它也显示a
的事实是由懒惰评估引起的。
如果没有延迟评估,它将首先评估ls()
(此时工作区中仅存在f
),将其复制到名为x
的函数中。然后该函数返回x
。在这种情况下,ls()
在创建a
之前进行评估。
但是,通过延迟评估,仅在需要表达式的结果时才计算表达式ls()
。在这种情况下,即函数返回并打印结果。那时全局环境已经改变(a
已创建),这意味着ls()
也显示a
。
(这也是您不希望函数使用<<-
更改全局工作区的原因之一。)