Why "object 'x' not found" on a line that does not use x?
I get this:
Error in paste0(width, on, k) : object 'x' not found
I'm utterly confused why it complains about 'x' on this particular line!
on
is a character, width
and k
are numbers. x
exists (it is a parameter of this function). That line and preceding ones look like:
print(index(x))
stopifnot(length(index(x))>=1)
#str(on);str(k);str(width)
extra=list( paste0(width,on,k) )
But what is even weirder when I added the commented out line it complains instead:
Error in str(on) : object 'x' not found
What triggered this question was a couple of call levels up I added this line:
rm(x)
( rm(list=c("x"))
gives same behaviour.)
So, I was expecting an "x not found" error. But not at that line (not even in that function)!
Background : I found a bug where code was relying on a global variable called x
, that should have been passed as a parameter. It worked in the unit test, failed in the real code, because the variable in question was not called 'x' in the real code!! So, I decided to explicitly remove each variable when finished with it, to discover if I have any more bugs of this kind.
(If the above code snippets aren't enough for someone to go "Aha, Darren, you still don't get how R works do you...", I'll try and create a minimal example to reproduce the problem.)
This was caused by x
being used to make one of the parameters to the function call Here is a minimal example:
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
It gives the error for line #AAA (see below), instead of at #BBB, as you might expect.
This is because attr
is a Primitive function. See http://cran.r-project.org/doc/manuals/r-release/R-lang.html#Builtin-objects-and-special-forms
(And I finally found confirmation that Primitive functions work the same way as promise objects, ie delay execution: http://cran.r-project.org/doc/manuals/R-ints.html#Argument-evaluation )
The error I get is as follows:
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")
Ie it complains about x
not existing on line 1, not line 9. You can make function f
much bigger, and not use on
until much deeper in the function, even pass it to another function, and the error does trigger until on
actually has to be evaluated. Eg this longer example:
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')) )
To spice up this example I've also added a parameter called x
to g()
. This mirrors the code in the original question, and it is easy to see how this can be confusing: "I have an x but it says it cannot see one!". To paraphrase Obi-Wan: "This is the not the x
you're looking for..."