[ruby-de] unsichtbare Hashwerte

Robert Klemme shortcutter at googlemail.com
Di Mai 2 16:54:10 JST 2017


2017-04-30 18:46 GMT+02:00 Marvin Gülker <m-guelker at phoenixmail.de>:

> 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.

Da stimme ich nicht zu:
* Zum einen ist das entscheidende Kriterium, das Du vermutlich im Sinn
hast, nicht "immediate value" oder normales Objekt, sondern
"immutable" vs. "mutable". Die "immediate values" sind eine
Optimierung des Ruby-Interpreters, die auf der Ebene der Sprache Ruby
keine Rolle spielen.
* Es gibt tatsächlich ein paar seltene Anwendungsfälle, in denen das
sinnvoll ist. Man kann z.B. den Default-Wert als "catch all"
verwenden:

h = Hash.new []

# Phase 1: Vorbereitung
special_values.each do |sv|
  h[sv] = []
end

# Phase 2: Sammeln
File.foreach do |line|
  key = line[/\d+/]
  h[key] << line
end

# Phase 3: Auswertung
h.each_pair do |k, v|
  printf "%p -> %p\n", k, v
end

puts "Rest:"
p h.default

>> 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.

Und der ist ja gespeichert - nur halt nicht unter irgendeinem Schlüssel. ;-)

> 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 { [] }

Wie gesagt, es hängt völlig vom Anwendungsfall ab. Und wieder geht es
nicht um "immediate" sondern um "immutable".

Die beiden häufigsten Anwendungsfälle dürften allerdings tatsächlich diese sein:
data = Hash.new {|h,k| h[k] = []}
...
data[item] << value

counters = Hash.new 0
...
counters[item] += 1

Ciao

robert

PS: Ich habe den Anlass genutzt mal etwas zusammen zu schreiben:
http://bLAZYog.blogspot.de/2017/05/common-misconceptions-about-immediate.html

-- 
[guy, jim, charlie].each {|him| remember.him do |as, often| as.you_can
- without end}
http://blog.rubybestpractices.com/


Mehr Informationen über die Mailingliste ruby-de