为什么在不使用x的行上"找不到'对象'x'?

Dar*_*ook 7 r

我明白了:

Error in paste0(width, on, k) : object 'x' not found
Run Code Online (Sandbox Code Playgroud)

我完全混淆为什么在这条特定的线上抱怨'x'!

on是一个字符,width并且k是数字.x存在(它是此函数的参数).该行和前面的行看起来像:

print(index(x))
stopifnot(length(index(x))>=1)
#str(on);str(k);str(width)
extra=list( paste0(width,on,k) )
Run Code Online (Sandbox Code Playgroud)

但是,当我添加注释掉的行时,甚至更奇怪的是抱怨:

Error in str(on) : object 'x' not found
Run Code Online (Sandbox Code Playgroud)

触发这个问题的原因是几个调用级别我添加了这一行:

rm(x)
Run Code Online (Sandbox Code Playgroud)

(rm(list=c("x"))给出相同的行为.)

所以,我期待一个"X找不到"错误.但不是那条线(甚至不是那个功能)!

背景:我发现了一个错误,代码依赖于一个名为的全局变量x,它应该作为参数传递.它在单元测试中工作,在实际代码中失败,因为有问题的变量在实际代码中没有被称为'x'!所以,我决定在完成它后显式删除每个变量,以发现我是否还有这种bug.

(如果上面的代码片段不足以让某人去"Aha,Darren,你仍然没有得到R的工作原理吗?",我会尝试创建一个最小的例子来重现这个问题.)

Dar*_*ook 4

这是由于x被用来作为函数调用的参数之一而引起的,这是一个最小的示例:

f=function(d,on){ print(on) } #AAA

x=1:4
attr(x,'extra')=list(a=1,b="xxx")
d=mean(x)

rm(x)   #Not needed any more

f(d, attr(x,'extra') )  # BBB
Run Code Online (Sandbox Code Playgroud)

它给出了 #AAA 行的错误(见下文),而不是您可能期望的 #BBB 行的错误。

这是因为attr是一个原始函数。请参阅http://cran.r-project.org/doc/manuals/r-release/R-lang.html#Builtin-objects-and-special-forms

(我最终发现原始函数的工作方式与 Promise 对象相同,即延迟执行:http://cran.r-project.org/doc/manuals/R-ints.html#Argument-evaluation


我得到的错误如下:

Error in print(on) : object 'x' not found
6: print(on) at dummy.R#1
5: f(d, (attr(x, "extra"))) at dummy.R#9
4: eval(expr, envir, enclos)
3: eval(ei, envir)
2: withVisible(eval(ei, envir))
1: source("dummy.R")
Run Code Online (Sandbox Code Playgroud)

也就是说,它抱怨x第 1 行不存在,而不是第 9 行。您可以使函数f变得更大,直到on函数更深入时才使用,甚至将其传递给另一个函数,并且错误会触发,直到on实际需要评估为止。例如这个更长的例子:

g=function(x,on){
    cat("Something else:",x,"\n")
    print(on)
}

f=function(d,on){
    cat("Do something:",d,"\n")
    g(d,on)
}

x=1:4
attr(x,'extra')=list(a=1,b="xxx")
d=mean(x)

rm(x)   #Not needed any more

f(d, (attr(x,'extra')) )
Run Code Online (Sandbox Code Playgroud)

为了使这个示例更加有趣,我还添加了一个名为 的x参数g()。这反映了原始问题中的代码,很容易看出这如何令人困惑:“我有一个 x,但它说它看不到一个!”。套用欧比旺的话:“这不是x你要找的……”

  • 惰性求值是 R 中的一个普遍特征,检查例如 `f <- function(a, b=c) {c = a^2; a*b}` 当您运行例如 `f(2)` 时,它运行良好,尽管第二个参数具有无效的默认值,但它是在运行时定义的。 (2认同)