ruby hash autovivification (facets)

后端 未结 3 829
予麋鹿
予麋鹿 2020-12-09 21:16

Here is a clever trick to enable hash autovivification in ruby (taken from facets):

  # File lib/core/facets/hash/autonew.rb, line 19
  def self.autonew(*arg         


        
相关标签:
3条回答
  • 2020-12-09 21:51

    The standard new method for Hash accepts a block. This block is called in the event of trying to access a key in the Hash which does not exist. The block is passed the Hash itself and the key that was requested (the two parameters) and should return the value that should be returned for the requested key.

    You will notice that the leet lambda does 2 things. It returns a new Hash with leet itself as the block for handling defaults. This is the behaviour which allows autonew to work for Hashes of arbitrary depth. It also assigns this new Hash to hsh[key] so that next time you request the same key you will get the existing Hash rather than a new one being created.

    0 讨论(0)
  • 2020-12-09 21:59

    It's also worth noting that this code can be made into a one-liner as follows:

    def self.autonew(*args)
      new(*args){|hsh, key| hsh[key] = Hash.new(&hsh.default_proc) }
    end
    

    The call to Hash#default_proc returns the proc that was used to create the parent, so we have a nice recursive setup here.

    I talk about a similar case to this on my blog.

    0 讨论(0)
  • 2020-12-09 22:17

    Alternatively, you might consider my xkeys gem. It's a module that you can use to extend arrays or hashes to facilitate nested access.

    If you look for something that doesn't exist yet, you get a nil value (or another value or an exception if you prefer) without creating anything by looking. It can also append to the end of arrays.

    You can opt to autovivify either hashes or arrays for integer keys (but just once for the entire structure).

    0 讨论(0)
提交回复
热议问题