rails - Método Ruby ''tap''-dentro de la asignación
rails tap (2)
En el primer caso, la array
y el punto apuntan al mismo objeto. Luego, muta ese objeto usando el método <<
. El objeto al que se array
tanto la array
como el punto de ary
ahora se cambia.
En el segundo caso, array
y ary
nuevamente apuntan a la misma matriz. Ahora reasigna la variable ary
, de modo que ary
ahora apunta a una nueva matriz. Sin embargo, la reasignación de ary
no tiene ningún efecto en la array
. En ruby, la reasignación de una variable nunca afecta a otras variables, incluso si apuntaban al mismo objeto antes de la reasignación.
En otras palabras, la array
aún está vacía por la misma razón que x
no será 42 en el siguiente ejemplo:
x = 23
y = x
y = 42 # Changes y, but not x
Editar: para agregar una matriz a otra en el lugar, puede usar el método concat
, que también debería ser más rápido que usar +=
.
Recientemente descubrí que el tap
se puede usar para "secamente" asignar valores a nuevas variables; por ejemplo, para crear y rellenar una matriz, como esto:
array = [].tap { |ary| ary << 5 if something }
Este código empujará 5
en la array
si something
es verdadero; de lo contrario, la array
permanecerá vacía.
Pero no entiendo por qué después de ejecutar este código:
array = [].tap { |ary| ary += [5] if something }
array
permanece vacía. ¿Alguien puede ayudarme?
Quiero ampliar esto un poco:
array = [].tap { |ary| ary << 5 if something }
Lo que esto hace (asumiendo que something
es verdadero):
asigna una
array
a[]
, una matriz vacía.array.object_id = 2152428060
Pasa
[]
al bloque comoary
.ary
yarray
están apuntando al mismo objeto de array.array.object_id = 2152428060 ary.object_id = 2152428060
ary << 5
<< es un método mutativo, lo que significa que modificará el objeto receptor. ¡Es similar al lenguaje de anexar!
a una llamada de método, que significa "¡modifique esto en su lugar!", como en.map
vs.map!
(aunque el bang no tiene ningún significado intrínseco en un nombre de método).ary
tiene 5 insertados, entoncesary
=array
=[5]
array.object_id = 2152428060 ary.object_id = 2152428060
Terminamos con la array
siendo igual a [5]
En el segundo ejemplo:
array = [].tap{ |ary| ary += [5] if something }
- mismo
- mismo
ary += 5
+=
es la abreviatura deary = ary + 5
, por lo que es la primera modificación (+
) y luego la asignación (=
), en ese orden. Da la apariencia de modificar un objeto en su lugar, pero en realidad no lo hace. Crea un objeto completamente nuevo.array.object_id = 2152428060 ary.object_id = 2152322420
Así que terminamos con la array
como el objeto original, una matriz vacía con object_id=2152428060
, y ary
, una matriz con un elemento que contiene 5 con object_id = 2152322420
. Nada le sucede a ary
después de esto. No está involucrado con la asignación original de la array
, que ya ha sucedido. Tap ejecuta el bloque después de que se haya asignado la array
.