问题描述
我对高级R"的3.36节中的问题4感到有些困惑( https://adv-r.hadley.nz/names-values.html ).我链接到的章节介绍了我在所附图像中使用的约定.我将简要总结一下.对于那些不熟悉这本书的人和那些不想单击链接并阅读作者对类似于我的图的描述的人,我在下面的图片中添加了我在图像中使用的约定的简要说明.这篇文章.
I'm a bit puzzled by question 4 in section 3.36 of "Advanced R" (https://adv-r.hadley.nz/names-values.html). The chapter that I have linked to explains the conventions I've used in the images I attached. I'll summarize them briefly. For those not familiar with the book and those who do not feel like clicking on the link and reading the authors description of diagrams similar to mine, I've added a brief explanation of the conventions I've used in the image below the rest of this post.
运行此代码会发生什么?画画
What happens when you run this code? Draw a picture
x <- list(1:10)
x[[2]] <- x
我了解这里正在创建什么. x <- list(1:10)
创建一个列表.该列表具有一个指向矢量1:10的元素. x[[2]] <- x
运行后,x指向包含两个元素的列表.第一个元素指向矢量1:10.第二个元素是对与原始列表相同的列表的引用(或者可能不仅与原始列表相同,而且实际上是原始列表吗?).我只是对在新列表中要复制和/或引用哪些对象(而不是变量,对象)感到困惑.
I understand what is being created here. x <- list(1:10)
creates a list. That list has one element that points to a vector 1:10. After x[[2]] <- x
runs, x points to a list with two elements. The first element points to a vector 1:10. The second element is a reference to a list that is identical to the original list (or maybe it is not just identical to the original, but is actually the original list?). I'm just confused about which objects (not variables, objects) are being copied and/or referenced to in the new list.
这是一种解决方案的尝试.
Here's an attempt at a solution.
仅运行x <- list(1:10)
之后,名称x绑定到列表对象.该列表有一个参考,即矢量(1:10).
After just running x <- list(1:10)
, the name x is bound to a list object. That list has one reference, which is to a vector (1:10).
这是我感到困惑的地方.我不确定执行x[[2]] <- x
时会发生什么.这是我的最佳猜测,我认为这是错误的.执行x[[2]] <- x
时,将创建x最初绑定到的对象的副本.对于该副本,将创建第二个元素,该元素指向原始对象.
Here's where I'm confused. I'm not sure what happens when x[[2]] <- x
is executed. Here's my best guess, which I think is wrong. When x[[2]] <- x
is executed, a copy of the object that x was originally bound to is made. For that copy, a second element is created which points to the original object.
我认为对x[[2]] <- x
执行时发生的情况的解释不正确.如果是这样,有人可以帮助我了解发生了什么吗?如果我碰巧是正确的,有人可以帮我解释为什么我是正确的吗?
I assume my interpretation of what happens when x[[2]] <- x
executes is incorrect. If so, can someone help me understand what is going on? And if I happen to be correct, can someone help explain why I am correct?
在我使用的图像中,圆角的正方形表示名称/变量.黑色箭头是从名称到对象的绑定(与分配箭头在R中指向的方向相反).当内部有绿色圆圈时,下面的矩形表示列表.绿色圆圈代表列表的元素.由于列表元素是对对象的引用,因此绿色箭头指向列表元素所引用的对象.
In the images I've used, a rounded square represents a name/variable. A black arrow is a binding from a name to an object (opposite to the direction the assignment arrow points in R). The rectangles below represent lists when there are green circles inside. The green circles represent an element of the list. Since list elements are references to objects, the green arrows point to the object that a list element is referencing to.
在第一张图片中,列表具有一个元素,并且该元素指向矢量1:10.
In the first image, the list has one element and that element points to the vector 1:10.
在第二个图像中,列表对象的第一个元素指向矢量1:10.第二个元素是对列表的引用.
In the second image, the first element of the list object points to the vector 1:10. The second element is a reference to a list.
推荐答案
也许会有所帮助.在这里,我们使用pryr::address
查看存储对象的内存位置(请注意,您的实际地址可能会有所不同,但是当我有匹配的地址时,您的地址也应该匹配).
Maybe this will help. Here we use pryr::address
to see the memory location where objects are stored (note, your actual addresses may vary, but when I have matching addresses, your addresses should match as well).
library(pryr)
x <- list(1:10)
pryr::address(x)
# [1] "0x3452810"
y <- x[[1]]
pryr::address(y)
# [1] "0x16b53bf0"
因此,在给定位置有一个列表x
.我们可以将R中的列表视为指向其他对象的指针的集合.我们不能直接获取存储它的第一项的地址(至少,我不知道address
是怎么回事),但是我们可以将该值存储到y
,因为R仅在对象存在时才会更改地址修改后,我们可以假定这是第一个值的存储位置.现在让我们更新x
So we have an list x
at a given location. We can think of lists in R as collections of pointers to other objects. We can't directly take the address of where it's storing it's first item (at least, I don't know how with address
), but we can store that value to y
and since R will only change address when objects are modified, we can assume this is where that first value is stored. Now let's update x
x[[2]] <- x
pryr::address(x)
# [1] "0x16001018"
我们可以看到x
已更改并被赋予了新的内存位置
we can see that x
has changed and been given a new memory location
y <- x[[1]]
pryr::address(y)
# [1] "0x16b53bf0"
请注意,尽管第一个元素仍位于相同的内存地址.因此,尚未创建此载体的新副本.新列表仅指向相同的向量.现在,让我们看一下我们刚刚添加的值的地址
Note that the first element though is still at the same memory address. So a new copy of this vector hasn't been made. The new list just points to that same vector. Now let's look at the address of the value we just added
y <- x[[2]]
pryr::address(y)
# [1] "0x3452810"
请注意,此值现在指向原始x
所在的旧内存地址.
Note that this value now points to the old memory address where the original x
lived.
还有更多
y <- x[[2]][[1]]
pryr::address(y)
# [1] "0x16b53bf0"
两个列表均指向相同的1:10向量.它只存储一次.
both lists point to the same 1:10 vector. It's only stored once.
因此,当您执行x[[2]]<-x
时,您正在做的是创建一个新列表.这个新列表实质上包含两个指针".一个指向原始列表中相同的向量,另一个指向列表的原始地址.
So when you do x[[2]]<-x
what you are doing is creating a new list. This new list contains two "pointers" essentially. One to the same vector that was in the original list, and one that points to the original address of the list.
这篇关于复制时修改;运行此代码时会发生什么? x<-list(1:10); x [[2]]<-x的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!