懒惰评估:为什么我不能使用情节(...,xlim = c(0,1),ylim = xlim)?

时间:2014-05-22 22:43:23

标签: r lazy-evaluation argument-passing

R最大的特色之一就是懒惰评估。这导致了经常遇到的样式,即可以使用参数作为另一个参数的值。例如,在Hadley关于Advanced R的好书中,您会看到this example

g <- function(a = 1, b = a * 2) {
  c(a, b)
}
g()
#> [1] 1 2
g(10)
#> [1] 10 20

现在,我想对xlimylim的情节做同样的事情,但它不起作用:

> plot(1, 1, ylim = c(0,1), xlim = ylim)
Error in plot.default(1, 1, ylim = c(0, 1), xlim = ylim) : 
  object 'ylim' not found
> plot(1, 1, xlim = c(0,1), ylim = xlim)
Error in plot.default(1, 1, xlim = c(0, 1), ylim = xlim) : 
  object 'xlim' not found
  • 有人知道为什么吗?
  • 有没有办法实现这个目标?

2 个答案:

答案 0 :(得分:13)

Quoting from the good manual:

  

4.3.3论证评估

     

关于评估的最重要的事情之一   函数的参数是提供的参数和默认值   参数的处理方式不同。提供的参数为   函数在调用的评估框架中进行评估   功能。函数的默认参数在。中计算   功能的评估框架。

要了解实际意义,请创建一个函数,其中一个参数的默认值是另一个参数值的函数:

f <- function(x=4, y=x^2) {
    y
}

当使用y默认值进行调用时,R会在函数调用的评估框架中评估y,即在整个相同的环境中函数体被评估 - x非常好(当然也有)的地方存在:

f() 
# [1] 16

使用y提供的值调用时,R查看调用函数的评估框架(此处为全局环境),找不到x,并让你知道它的错误信息:

f(y=x^2)
# Error in f(y = x^2) : object 'x' not found

答案 1 :(得分:5)

这里有一个范围问题。在语句plot(1, 1, ylim = c(0,1), xlim = ylim)中,名称ylim仅作为参数的名称提供,并且通常不对调用者可用。

对于要在赋值右侧使用的变量,它必须在调用范围内可用。

您的第一个示例有效的原因是您将默认参数写入函数定义, 可以访问所有参数。

一种可能的解决方法,只有在很多情况下这是相同的默认值时才有意义,就是将 plot 函数包装在一个新的函数中有这种行为。

myplot <- function(x, y, ylim, xlim = ylim,...) {
  plot(x,y, ylim = ylim, xlim = xlim,...)
}

myplot(1,1, ylim=c(0,1))