R中未评估的论点

时间:2017-02-13 07:15:59

标签: r lazy-evaluation

我还是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"

为什么会这样?有人可以帮助我吗?

1 个答案:

答案 0 :(得分:3)

问题1

这与懒惰评估无关。

函数返回它执行的最后一个语句的结果。在这种情况下,最后一个语句是a <- 1a <- 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

(这也是您不希望函数使用<<-更改全局工作区的原因之一。)