views:

74

answers:

2

Hi everyone,

This

x <- list(12, 13)
names(y <- x) <- c("a", "b")

gives the error:

Error in names(y <- x) <- c("a", "b") : object 'y' not found

Can anyone explain why?

According to R's rules of evaluation y <- x should be evaluated inside the parent frame of names<-. So y should be created in global environment.

Thanks.

[update] If object y is already present in the global environment, then the error is:

Error in names(y <- x) <- c("a", "b") : could not find function "<-<-"

[update2] Here it is, another construct, which I encountered today.

(X <- matrix(0, nrow = 10, ncol = 10))[1:3] <- 3:5
Error during wrapup: object 'X' not found
+1  A: 

This is probably due to lazy evaluation. There is little guarentee what order things will be done in when doing multiple tasks in one line. Apparently in this case it tries to find y before evaluating the assignment. If you just ask for the names, then y is assigned.

It is best to do these types of things in 2 steps so you can be assured that the first is done before the second needs the results.

Greg Snow
In programs, one would certainly do it in two lines. But for interactive use this type of R-ish tricks could be very useful.
VitoshKa
I find it very hard to imagine an interactive situation where this would be necessary
hadley
@hadley Creation of a new object as above is one such an example. I often do that in if and apply type of forms. R core code has instances of such constructs as well.
VitoshKa
@hadley Above I meant the use of the assignment inside other calls of course. The assignment inside an assignment is indeed a peculiar thing. My example is probably the most useful among others. In any case the question is theoretical. I wonder what is really going on there.
VitoshKa
But your example is pointless - you'd just do `list(aa = 23, bb = 2323)`
hadley
@hadley My original situation was like this. I had an `x` object without names, and I wanted to create a new object like `x` but with names. I updated the question.
VitoshKa
Thy question is "why is that happening?" and not "how can I write it differently?". I know I can make it with structure(..), setNames(..) or in two lines of code, but this does not solve the question.
VitoshKa
+2  A: 

This is related to the way that <- recursively transforms the LHS, appending "<-" to the names of functions to get the replacement form. The first argument is treated specially. Note the difference between the last two:

x <- a <- 1
`f<-` <- function(x, a, value) x
f(x, a <- 2) <- 2
f(x <- 2, a) <- 2
# Error in f(x <- 2, a) <- 2 : could not find function "<-<-"

For what you're trying to do, I'd use setNames anyway.

Charles
@Charles thanks. I was not aware of setNames function (in stats! package). You would probably want to change the `f<-` to return `value` instead of `x`, otherwise the func does nothing. My question is mainly technically-conceptual, I just want to know what is going on with this assignment; not necesarlly what I would use this construct for this purpose. It happens once, though, when I discovered the problem :)
VitoshKa
Yeah f isn't supposed to be accomplishing anything here, rather serving to show the difference in treatment for the initial argument. The assignment to a is ok, but the assignment to x gets transformed. The recursive transformation is what allows eg x[1][2][3] <- 4 to work (conceptually x <- `[<-`(x, 1, `[<-`(x[1], 2, `[<-`(x[1][2], 3, 4))), though R uses a `*tmp*` variable).
Charles
@Charles Internal transformations into f<- does not explain the error. As Marek pointed in the comment to my question, names<-(...)<- works just fine. Your point about special treatment of the first variable is a valid one. But it's not clear in what sense it is special and what is really happening internally.
VitoshKa
If you try f(g(x)) <- blah, you need to have both an `f<-`, *and* a `g<-`, because it needs to be able to propagate the assigned value. Thats why its looking for `<-<-`.
Charles