[ruby-de] unsichtbare Hashwerte

Marvin Gülker m-guelker at phoenixmail.de
Mo Mai 1 01:46:45 JST 2017


Hi,

On Sun, Apr 30, 2017 at 06:22:21PM +0200, Die Optimisten wrote:
> h=Hash.new([])    => {}

So solltest du niemals einen Standardwert für ein Hash festlegen, wenn
es sich nicht um einen Immediate Value handelt. Was passiert, ist, dass
*dasselbe* Array-Objekt für jeden Schlüssel zurückgegeben wird, den es
noch nicht gibt.

> h[1]<< 111    => [111]       # ein Array als Value

h[1] existiert noch nicht. Also gibt dir dies das Array-Objekt von oben
zurück. An dieses fügst du dann 111 an, speicherst das Ergebnis aber
nicht wieder im Hash.

Das bloße Abrufen eines Standardwerts verändert das Hash nicht. Das wäre
auch bei einem anderen Standardwert nicht anders gewesen:

    irb(main):005:0> hsh = Hash.new(6)
    => {}
    irb(main):006:0> hsh["foo"]
    => 6
    irb(main):007:0> hsh
    => {}

> h                      => {}            # Warum denn das?!?

Daher ist das Hash leer.

> h[1]                => [111]        # der Wert ist doch gespeichert!

Nein, ist er nicht. h[1] existiert immer noch nicht, deshalb wird dir
nur wieder der Standardwert zurückgegeben. Den hattest du modifiziert,
und so erhältst du den modifizierten Standardwert zurück.

> danke
> Andreas

Um zumindest die unerwartete Modifikation zu vermeiden, solltest du den
Standardwert für Werte, die keine Immediate Values sind -- wie eben
Arrays -- über einen Proc festlegen.

    h = Hash.new { [] }

Willst du automatisches Einfügen, dann geht das auch:

    irb(main):008:0> hsh = Hash.new{|h, k| h[k] = []}
    => {}
    irb(main):009:0> hsh[1] << 111
    => [111]
    irb(main):010:0> hsh
    => {1=>[111]}

Viele Grüße
Marvin

-- 
Blog: https://www.guelkerdev.de
PGP/GPG ID: F1D8799FBCC8BC4F


Mehr Informationen über die Mailingliste ruby-de