Estoy aprendiendo R y actualmente estoy leyendo este libro . Para asegurarme de que entiendo el concepto, realicé la siguiente prueba que resultó ser bastante confusa para mí y agradecería si pudiera aclararla. Aquí está la prueba, que ejecuté directamente en el shell R desde el terminal (sin usar RStudio o Emacs ESS).
> library(lobstr)
>
> x <- c(1500,2400,8800)
> y <- x
> ### So the following two lines must return the same memory address
> obj_addr(x)
[1] "0xb23bc50"
> obj_addr(y)
[1] "0xb23bc50"
> ### So as I expected, indeed both x and y point to the same memory
> ### location: 0xb23bc50
>
>
>
> ### Now let's check that each element can be referenced by the same
> ### memory address either by using x or y
> x[1]
[1] 1500
> y[1]
[1] 1500
> obj_addr(x[1])
[1] "0xc194858"
> obj_addr(y[1])
[1] "0xc17db88"
> ### And here is exactly what I don't understand: x and y point
> ### to the same memory address, so the same must be true for
> ### x[1] and y[1]. So how come I obtain two different memory
> ### addresses for the same element of the same vector?
>
>
>
> x[2]
[1] 2400
> y[2]
[1] 2400
> obj_addr(x[2])
[1] "0xc15eca0"
> obj_addr(y[2])
[1] "0xc145d30"
> ### Same problem!
>
>
>
> x[3]
[1] 8800
> y[3]
[1] 8800
> obj_addr(x[3])
[1] "0xc10e9b0"
> obj_addr(y[3])
[1] "0xc0f78e8"
> ### Again the same problem: different memory addresses
¿Podría decirme dónde está mi error y qué he entendido mal en este problema?
obj_addr(x[1])
dos veces debería darle resultados diferentes, ya que cada nuevo entero tendrá su propia dirección.Respuestas:
Cualquier objeto R es una C (llamada puntero
SEXP
- a) "multi-objeto" (struct
). Esto incluye información (que R necesita para operar, por ejemplolength
, número de referencias -para saber cuándo copiar un objeto- y más) sobre el objeto R y, también, los datos reales del objeto R al que tenemos acceso.lobstr::obj_addr
, presumiblemente, devuelve la dirección de memoria que unSEXP
apunta. Esa parte de la memoria contiene tanto la información como los datos del objeto R. Desde el entorno R no podemos / no necesitamos acceder a la memoria (puntero a) de los datos reales en cada objeto R.Como Adam señala en su respuesta, la función
[
copia el enésimo elemento de los datos contenidos en el objeto C a un nuevo objeto C y devuelve suSEXP
puntero a R. Cada vez que[
se llama, se crea un nuevo objeto C y se devuelve a R.No podemos acceder a la dirección de memoria de cada elemento de los datos reales de nuestro objeto a través de R. Pero jugando un poco, podemos rastrear las direcciones respectivas usando la API C:
Una función para obtener las direcciones:
Y aplicando a nuestros datos:
La diferencia de memoria sucesiva entre los elementos de datos de nuestro objeto es igual al tamaño del
int
tipo:Usando la
[
función:Esta podría ser una respuesta extensa más de la necesaria y es simplista en cuanto a los tecnicismos reales, pero, con suerte, ofrece una imagen "más grande" más clara.
fuente
Esta es una forma de verlo. Estoy seguro de que hay una visión más técnica. Recuerde que en R, casi todo es una función. Esto incluye la función de extracto,
[
. Aquí hay una declaración equivalente ax[1]
:Entonces, lo que está haciendo es ejecutar una función que devuelve un valor (verifique
?Extract
). Ese valor es un entero. Cuando ejecutaobj_addr(x[1])
, está evaluando la funciónx[1]
y luego le da elobj_addr()
retorno de esa función, no la dirección del primer elemento de la matriz que vincula a ambosx
yy
.fuente