在嵌套函数中评估替换表达式时出现意外强制

时间:2015-11-30 19:26:07

标签: r promise metaprogramming lazy-evaluation substitution

检查R的承诺是如何运作的,我认识到了一个我无法解释的效果。请考虑以下代码:

twice3 <- function(i) {
  eval.subst <- function() eval(substitute(i))

  print("one")
  substitute(i)
  print("two")
  eval(substitute(i))
  print("three")
  eval(substitute(i))
  print("four")
  eval.subst()
  print("five")
  eval.subst()
}

这应该测试在我尝试评估promise中的表达式时发生的各种事情,而不强制承诺本身。这就是我得到的:

> twice3({print("hi"); 10})
[1] "one"
[1] "two"
[1] "hi"
[1] "three"
[1] "hi"
[1] "four"
[1] "hi"
[1] "five"
[1] 10

观察:

  • substitute不评估或强迫任何事情。
  • eval(substitute(i))也没有强制原先的承诺,这是我所期待的。它可能会得到表达式并对其进行求值,而不会触及i的值部分。
  • 然而,
  • eval.subst应该与eval(substitute(i))做同样的事情, 显示一些意外的缓存。起初,我认为只关注它的回报值,但是......
  • 正如我们在"five"之后看到的那样,eval.subst的调用已经评估了i

为什么最后一次效果会发生?我可以解释的唯一方法是在eval.subst内,i指的是封闭的东西,而不是“直接”到外部i;但无论如何,如果我先替换,为什么会改变呢?

TL; DR 这里有什么区别:

> f1 <- function(i) {
+   eval.subst <- function() eval(substitute(i))
+   print('one')
+   eval.subst()
+   print('two')
+   i
+ }
> f1({print('hi'); 10})
[1] "one"
[1] "hi"
[1] "two"
[1] 10

> f2 <- function(i) {
+   print('one')
+   eval(substitute(i))
+   print('two')
+   i
+ }
> f2({print('hi'); 10})
[1] "one"
[1] "hi"
[1] "two"
[1] "hi"
[1] 10

0 个答案:

没有答案