懒惰评估:为啥我不能使用 plot(..., xlim = c(0,1), ylim = xlim)?
Posted
技术标签:
【中文标题】懒惰评估:为啥我不能使用 plot(..., xlim = c(0,1), ylim = xlim)?【英文标题】:Lazy Evaluation: Why can't I use plot(..., xlim = c(0,1), ylim = xlim)?懒惰评估:为什么我不能使用 plot(..., xlim = c(0,1), ylim = xlim)? 【发布时间】:2014-07-12 03:59:09 【问题描述】: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
现在,我想对 xlim
和 ylim
的绘图做同样的事情,但是它不起作用:
> 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
有人知道为什么吗?
还有办法实现这一目标吗?
【问题讨论】:
我认为这很容易用adv-r.had.co.nz/Environments.html 中的更新定义来解释:默认参数评估函数的执行环境,提供的参数评估函数的调用环境。 【参考方案1】:Quoting from the good manual:
4.3.3 参数评估
关于评估的最重要的事情之一 函数的参数是提供的参数和默认值 论据被区别对待。为 a 提供的参数 函数在调用的评估框架中进行评估 功能。函数的默认参数在 函数的评估框架。
要了解这在实践中意味着什么,请创建一个函数,其中一个参数的默认值是另一个参数值的函数:
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
【讨论】:
最后一行很有趣。因此,即使您已将默认x
值设置为 4,R 也不会在评估框架中找到它?显然“不”,但有点难以理解为什么。
@RichardScriven -- 是的,这就是我使用这个例子的原因 :-) 直到你真正完全掌握它的那一刻,你才会感到舒服! (对我来说,那一刻是在第一次阅读那篇文章几年后出现的;希望这将有助于加快其他人的进程!)
...这可能不会太远,因为您现在让我感到好奇。 :) 我也不知道默认函数参数会进入全局环境。我认为他们留在了函数环境中,而函数进入了全局环境。我有读书要做!
有没有办法强制在函数调用的框架内评估提供的参数?例如,与常见的嫌疑人之一:eval
、substitute
、...
不,没有办法。不过,您可以设置一个函数来对提供的参数进行非标准评估。例如,想想将公式作为参数的函数,或者看看 curve
函数对其初始 expr
参数的作用。【参考方案2】:
这里有一个范围界定问题。在语句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))
【讨论】:
但是为什么它在上面的例子中有效(对不起,第一个例子是错误的)? @Henrik,我刚刚更新了。第二种情况是一个函数call,它的作用域是调用者的上下文。第一个场景是一个函数定义,它的作用域是被调用者的上下文。 @Henrik,我还更新了一个有点弱的解决方法。以上是关于懒惰评估:为啥我不能使用 plot(..., xlim = c(0,1), ylim = xlim)?的主要内容,如果未能解决你的问题,请参考以下文章
为啥除了 Pixel XL 设备在 android studio 模拟器中所有 ADV 设备都不能工作?
为啥我不能将 x 和 y 标签设置为 pd.plot() 的参数,而我可以轻松设置类似的东西,例如标题?