Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why "object 'x' not found" on a line that does not use x?

Tags:

r

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.)

like image 345
Darren Cook Avatar asked Jun 26 '13 02:06

Darren Cook


1 Answers

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, i.e. 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")

I.e. 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. E.g. 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..."

like image 77
Darren Cook Avatar answered Sep 27 '22 18:09

Darren Cook