RubyIntermedio8 oct 2025

¡Atajos Peligrosos! La Mutación Silenciosa de Hashes

snippet.ruby
def add_default_value(hash, key, default_value = [])
  hash[key] ||= default_value
end

hash1 = {}
add_default_value(hash1, :items)
hash1[:items] << 1

hash2 = {}
add_default_value(hash2, :items)
hash2[:items] << 2

puts hash1.inspect
puts hash2.inspect

¿Qué crees que imprime?

Salida Esperada

{:items=>[1]}
{:items=>[2]}

⚠️ Salida Real

{:items=>[1, 2]}
{:items=>[1, 2]}

¿Por qué pasa esto?

¡Oh, la pereza! 😅 En Ruby, el operador `||=` (o igual) puede ser un arma de doble filo. En este caso, estamos intentando inicializar un hash con un valor por defecto si la clave no existe. El problema es que `default_value = []` se evalúa solo una vez. ¡UNA SOLA VEZ! 😱 Esto significa que `hash1[:items]` y `hash2[:items]` apuntan al **MISMO** array en memoria. 🤯 Cuando modificamos `hash1[:items]`, ¡también estamos modificando `hash2[:items]` y viceversa! Es como si tuvieran la misma cuenta bancaria y uno le echa la culpa al otro de los gastos. **Solución**: Crear una nueva instancia del array por defecto cada vez. Por ejemplo: `hash[key] ||= default_value.dup` o `hash[key] ||= []`.

Conceptos relacionados

hashmutationdefault-value