From: Eric Wong Date: 2011-11-12T09:26:56+09:00 Subject: Re: The fastest way to read files Ryan Davis wrote: > On Nov 11, 2011, at 15:20 , Robert Klemme wrote: > > On Fri, Nov 11, 2011 at 10:07 PM, Ryan Davis wrote: > >> On Nov 11, 2011, at 04:50 , Robert Klemme wrote: > >> > >>> # ensure every word is only once in memory > >>> words = Hash.new {|h,k| k.freeze; h[k] = k} > >> > >> AFAIK, Ruby hashes have (almost) always frozen their keys. > > > > I know. That's the reason why I do the freeze in the block. > > I'm confused. If you know that the key is going to be frozen anyways, > why freeze it? The implicit freeze from Hash#[]= duplicates the string and freezes the duplicate, not the same object given by the user. Explicitly freezing the key before Hash#[]= prevents MRI[1] from duplicating the string. ------------------------ freeze_example.rb -------------------- h = {} frozen = "foo".freeze h[frozen] = true # explicitly freezing the key means the String object is stored as-is p [ :frozen_original_key, frozen.object_id ] p [ :frozen_key_after_aset, h.keys[0].object_id ] h = {} not_frozen = "foo" h[not_frozen] = true # Not freezing means the key stored in the hash key is a different # object than the one provided by the user. p [ :not_frozen_original_key, not_frozen.object_id ] p [ :not_frozen_key_after_aset, h.keys[0].object_id ] ------------------------ Output -------------------------------- [:frozen_original_key, 70096844693360] [:frozen_key_after_aset, 70096844693360] [:not_frozen_original_key, 70096844693120] [:not_frozen_key_after_aset, 70096844694120] [1] - Verified by reading rb_hash_aset() in hash.c which eventually calls rb_str_new_frozen() in string.c (ruby/trunk): rb_str_new_frozen(VALUE orig) { VALUE klass, str; if (OBJ_FROZEN(orig)) return orig; ...