2009-11-30 44 views
12

Ok, así que quería crear un hash que tenga un hash vacío como valor predeterminado. Un poco raro, lo sé, pero digamos que pensé que podría ser útil.¿Por qué Hash.new ({}) oculta los miembros hash?

Así que aquí es lo que hice:

>> a = Hash.new({}) 
=> {} 
>> a[:a][:b] = 5 
=> 5 
>> a 
=> {} 
>> a[:a] 
=> {:b=>5} 
>> a.keys 
=> [] 
>> a.size 
=> 0 
>> a[:a].size 
=> 1 

En otras palabras, no veo miembro de hash cuando inspecciono el hash, pero no puedo acceder a él mediante su clave.

¿Este comportamiento es esperado? ¿Que esta pasando aqui?

Por cierto, esto es Ruby 1.9.1, no he probado versiones anteriores.

Editar: simplificado ejemplo, ya que no tiene por qué ser un hash de hashes de hashes ...

+0

Reproducible en 1.8.7 también. –

Respuesta

17

Se espera un comportamiento (en todas las versiones de rubí). Y si usted experimenta un poco más lejos, verá que siempre se accede al mismo hash, no importa qué tecla se usa:

>> a[:a][:b] = 1 
=> 1 
>> a[:c][:d] = 2 
=> 2 
>> a[:d] 
=> {:b=>1, :d=>2} 

La forma Hash.new con un argumento predeterminado funciona es: Si lo hace hash[key] comprueba si esa clave existe en el hash. Si lo hace, devuelve el valor de esa clave. Si no, devuelve el valor predeterminado. No agrega la clave al hash y devolverá el mismo objeto predeterminado (no una copia) cada vez.

Para obtener lo que desea, desea especificar un bloque predeterminado en su lugar. De esta forma, el bloque se ejecutará cada vez que acceda a una clave que no está en el hash. Dentro del bloque puede crear un nuevo hash y establecer la clave para "apuntar" a ese hash. De la misma manera:

Hash.new { |h,k| h[k] = {} } 
+0

Básicamente, agregó las claves al valor predeterminado, no su hash. – Riking

Cuestiones relacionadas