def [](key)
      case key
      when Element, MissingElement
        raise ArgumentError, "wrong type" unless key.type == self
        key
      when Symbol
        elements_by_name.fetch(key)
      else
        key = normalize_value(key)
        elements_by_value.fetch(key) { MissingElement.new key, self }
      end
    end
def [](key)
      case key
      when Element, MissingElement
        raise ArgumentError, "wrong type" unless key.type == self
        key
      when Symbol
        elements_by_name.fetch(key)
      else
        key = normalize_value(key)
        elements_by_value.fetch(key) { MissingElement.new key, self }
      end
    end
Initialize takes a single hash of name to value.

 e.g. MetaEnum::Type.new(red: 0, green: 1, blue: 2)

 Additional data can also be associated with each value by passing an array
 of [value, extra data]. This can be used for additional description or
 any other reason.

 e.g. MetaEnum::Type.new(small: [0, "Less than 10], large: [1, "At least 10"]

 value_normalizer is a callable object that normalizes values. The default
 converts all values to integers. To allow string values use method(:String).

 element_class is the class with which to create elements. It should be a
 sub-class of MetaEnum::Element (or otherwise match it's behavior).
 [] is a "do what I mean" operator. It returns the Element from this type depending on the key.

 When key is a symbol, it is considered the name of the Element to return.
 Since symbols are used from code, it is considered an error if the key is
 not found and it raises an exception.

 When key can be converted to an integer by value_normalizer, then it is
 considered the value of the Element to return. Retrieving by value is
 presumed to converting from external data where a missing value should not
 be considered fatal. In this case it returns a MissingElement is with value
 as the key. This allows a Type to only specify the values it needs while
 passing through the others unmodified.

 Finally, when key is a MetaEnum::Element, it is simply returned (unless it
 belongs to a different Type in which case an ArgumentError is raised).

 See #values_by_number and #values_by_name for non-fuzzy value selection.