Index: EcnlProtoTool/trunk/mruby-2.1.1/mrbgems/mruby-hash-ext/mrbgem.rake
===================================================================
--- EcnlProtoTool/trunk/mruby-1.3.0/mrbgems/mruby-hash-ext/mrbgem.rake	(revision 331)
+++ EcnlProtoTool/trunk/mruby-2.1.1/mrbgems/mruby-hash-ext/mrbgem.rake	(revision 439)
@@ -3,5 +3,4 @@
   spec.author  = 'mruby developers'
   spec.summary = 'Hash class extension'
-  spec.add_dependency 'mruby-enum-ext', :core => 'mruby-enum-ext'
-  spec.add_dependency 'mruby-array-ext', :core => 'mruby-array-ext'
+  spec.add_dependency 'mruby-array-ext', core: 'mruby-array-ext'
 end
Index: EcnlProtoTool/trunk/mruby-2.1.1/mrbgems/mruby-hash-ext/mrblib/hash.rb
===================================================================
--- EcnlProtoTool/trunk/mruby-1.3.0/mrbgems/mruby-hash-ext/mrblib/hash.rb	(revision 331)
+++ EcnlProtoTool/trunk/mruby-2.1.1/mrbgems/mruby-hash-ext/mrblib/hash.rb	(revision 439)
@@ -28,7 +28,7 @@
     if length == 1
       o = object[0]
-      if o.respond_to?(:to_hash)
+      if Hash === o
         h = self.new
-        object[0].to_hash.each { |k, v| h[k] = v }
+        o.each { |k, v| h[k] = v }
         return h
       elsif o.respond_to?(:to_a)
@@ -63,23 +63,4 @@
   ##
   # call-seq:
-  #     Hash.try_convert(obj) -> hash or nil
-  #
-  # Try to convert <i>obj</i> into a hash, using to_hash method.
-  # Returns converted hash or nil if <i>obj</i> cannot be converted
-  # for any reason.
-  #
-  #     Hash.try_convert({1=>2})   # => {1=>2}
-  #     Hash.try_convert("1=>2")   # => nil
-  #
-  def self.try_convert(obj)
-    if obj.respond_to?(:to_hash)
-      obj.to_hash
-    else
-      nil
-    end
-  end
-
-  ##
-  # call-seq:
   #     hsh.merge!(other_hash)                                 -> hsh
   #     hsh.merge!(other_hash){|key, oldval, newval| block}    -> hsh
@@ -102,5 +83,5 @@
 
   def merge!(other, &block)
-    raise TypeError, "can't convert argument into Hash" unless other.respond_to?(:to_hash)
+    raise TypeError, "Hash required (#{other.class} given)" unless Hash === other
     if block
       other.each_key{|k|
@@ -114,4 +95,49 @@
 
   alias update merge!
+
+  ##
+  # call-seq:
+  #   hsh.compact!    -> hsh
+  #
+  # Removes all nil values from the hash. Returns the hash.
+  # Returns nil if the hash does not contain nil values.
+  #
+  #   h = { a: 1, b: false, c: nil }
+  #   h.compact!     #=> { a: 1, b: false }
+  #
+
+  def compact!
+    keys = self.keys
+    nk = keys.select{|k|
+      self[k] != nil
+    }
+    return nil if (keys.size == nk.size)
+    h = {}
+    nk.each {|k|
+      h[k] = self[k]
+    }
+    h
+    self.replace(h)
+  end
+
+  ##
+  # call-seq:
+  #    hsh.compact     -> new_hsh
+  #
+  # Returns a new hash with the nil values/key pairs removed
+  #
+  #    h = { a: 1, b: false, c: nil }
+  #    h.compact     #=> { a: 1, b: false }
+  #    h             #=> { a: 1, b: false, c: nil }
+  #
+  def compact
+    h = {}
+    self.keys.select{|k|
+      self[k] != nil
+    }.each {|k|
+      h[k] = self[k]
+    }
+    h
+  end
 
   ##
@@ -150,5 +176,5 @@
         none
       else
-        raise KeyError, "Key not found: #{key}"
+        raise KeyError, "Key not found: #{key.inspect}"
       end
     else
@@ -172,5 +198,5 @@
 
   def delete_if(&block)
-    return to_enum :delete_if unless block_given?
+    return to_enum :delete_if unless block
 
     self.each do |k, v|
@@ -229,5 +255,5 @@
 
   def keep_if(&block)
-    return to_enum :keep_if unless block_given?
+    return to_enum :keep_if unless block
 
     keys = []
@@ -285,9 +311,5 @@
   #
   def <(hash)
-    begin
-      hash = hash.to_hash
-    rescue NoMethodError
-      raise TypeError, "can't convert #{hash.class} to Hash"
-    end
+    raise TypeError, "can't convert #{hash.class} to Hash" unless Hash === hash
     size < hash.size and all? {|key, val|
       hash.key?(key) and hash[key] == val
@@ -309,9 +331,5 @@
   #
   def <=(hash)
-    begin
-      hash = hash.to_hash
-    rescue NoMethodError
-      raise TypeError, "can't convert #{hash.class} to Hash"
-    end
+    raise TypeError, "can't convert #{hash.class} to Hash" unless Hash === hash
     size <= hash.size and all? {|key, val|
       hash.key?(key) and hash[key] == val
@@ -333,9 +351,5 @@
   #
   def >(hash)
-    begin
-      hash = hash.to_hash
-    rescue NoMethodError
-      raise TypeError, "can't convert #{hash.class} to Hash"
-    end
+    raise TypeError, "can't convert #{hash.class} to Hash" unless Hash === hash
     size > hash.size and hash.all? {|key, val|
       key?(key) and self[key] == val
@@ -357,9 +371,5 @@
   #
   def >=(hash)
-    begin
-      hash = hash.to_hash
-    rescue NoMethodError
-      raise TypeError, "can't convert #{hash.class} to Hash"
-    end
+    raise TypeError, "can't convert #{hash.class} to Hash" unless Hash === hash
     size >= hash.size and hash.all? {|key, val|
       key?(key) and self[key] == val
@@ -383,3 +393,108 @@
     end
   end
+
+  ##
+  # call-seq:
+  #    hsh.transform_keys {|key| block } -> new_hash
+  #    hsh.transform_keys                -> an_enumerator
+  #
+  # Returns a new hash, with the keys computed from running the block
+  # once for each key in the hash, and the values unchanged.
+  #
+  # If no block is given, an enumerator is returned instead.
+  #
+  def transform_keys(&block)
+    return to_enum :transform_keys unless block
+    hash = {}
+    self.keys.each do |k|
+      new_key = block.call(k)
+      hash[new_key] = self[k]
+    end
+    hash
+  end
+  ##
+  # call-seq:
+  #    hsh.transform_keys! {|key| block } -> hsh
+  #    hsh.transform_keys!                -> an_enumerator
+  #
+  # Invokes the given block once for each key in <i>hsh</i>, replacing it
+  # with the new key returned by the block, and then returns <i>hsh</i>.
+  #
+  # If no block is given, an enumerator is returned instead.
+  #
+  def transform_keys!(&block)
+    return to_enum :transform_keys! unless block
+    self.keys.each do |k|
+      value = self[k]
+      self.__delete(k)
+      k = block.call(k) if block
+      self[k] = value
+    end
+    self
+  end
+  ##
+  # call-seq:
+  #    hsh.transform_values {|value| block } -> new_hash
+  #    hsh.transform_values                  -> an_enumerator
+  #
+  # Returns a new hash with the results of running the block once for
+  # every value.
+  # This method does not change the keys.
+  #
+  # If no block is given, an enumerator is returned instead.
+  #
+  def transform_values(&b)
+    return to_enum :transform_values unless block_given?
+    hash = {}
+    self.keys.each do |k|
+      hash[k] = yield(self[k])
+    end
+    hash
+  end
+
+  ##
+  # call-seq:
+  #    hsh.transform_values! {|key| block } -> hsh
+  #    hsh.transform_values!                -> an_enumerator
+  #
+  # Invokes the given block once for each value in the hash, replacing
+  # with the new value returned by the block, and then returns <i>hsh</i>.
+  #
+  # If no block is given, an enumerator is returned instead.
+  #
+  def transform_values!(&b)
+    return to_enum :transform_values! unless block_given?
+    self.keys.each do |k|
+      self[k] = yield(self[k])
+    end
+    self
+  end
+
+  def to_proc
+    ->x{self[x]}
+  end
+
+  ##
+  # call-seq:
+  #   hsh.fetch_values(key, ...)                 -> array
+  #   hsh.fetch_values(key, ...) { |key| block } -> array
+  #
+  # Returns an array containing the values associated with the given keys
+  # but also raises <code>KeyError</code> when one of keys can't be found.
+  # Also see <code>Hash#values_at</code> and <code>Hash#fetch</code>.
+  #
+  #   h = { "cat" => "feline", "dog" => "canine", "cow" => "bovine" }
+  #
+  #   h.fetch_values("cow", "cat")                   #=> ["bovine", "feline"]
+  #   h.fetch_values("cow", "bird")                  # raises KeyError
+  #   h.fetch_values("cow", "bird") { |k| k.upcase } #=> ["bovine", "BIRD"]
+  #
+  def fetch_values(*keys, &block)
+    keys.map do |k|
+      self.fetch(k, &block)
+    end
+  end
+
+  alias filter select
+  alias filter! select!
 end
Index: EcnlProtoTool/trunk/mruby-2.1.1/mrbgems/mruby-hash-ext/src/hash-ext.c
===================================================================
--- EcnlProtoTool/trunk/mruby-1.3.0/mrbgems/mruby-hash-ext/src/hash-ext.c	(revision 331)
+++ EcnlProtoTool/trunk/mruby-2.1.1/mrbgems/mruby-hash-ext/src/hash-ext.c	(revision 439)
@@ -37,4 +37,35 @@
 }
 
+/*
+ *  call-seq:
+ *     hsh.slice(*keys) -> a_hash
+ *
+ *  Returns a hash containing only the given keys and their values.
+ *
+ *     h = { a: 100, b: 200, c: 300 }
+ *     h.slice(:a)           #=> {:a=>100}
+ *     h.slice(:b, :c, :d)   #=> {:b=>200, :c=>300}
+ */
+static mrb_value
+hash_slice(mrb_state *mrb, mrb_value hash)
+{
+  mrb_value *argv, result;
+  mrb_int argc, i;
+
+  mrb_get_args(mrb, "*", &argv, &argc);
+  result = mrb_hash_new_capa(mrb, argc);
+  if (argc == 0) return result; /* empty hash */
+  for (i = 0; i < argc; i++) {
+    mrb_value key = argv[i];
+    mrb_value val;
+
+    val = mrb_hash_fetch(mrb, hash, key, mrb_undef_value());
+    if (!mrb_undef_p(val)) {
+      mrb_hash_set(mrb, result, key, val);
+    }
+  }
+  return result;
+}
+
 void
 mrb_mruby_hash_ext_gem_init(mrb_state *mrb)
@@ -44,4 +75,5 @@
   h = mrb->hash_class;
   mrb_define_method(mrb, h, "values_at", hash_values_at, MRB_ARGS_ANY());
+  mrb_define_method(mrb, h, "slice",     hash_slice, MRB_ARGS_ANY());
 }
 
Index: EcnlProtoTool/trunk/mruby-2.1.1/mrbgems/mruby-hash-ext/test/hash.rb
===================================================================
--- EcnlProtoTool/trunk/mruby-1.3.0/mrbgems/mruby-hash-ext/test/hash.rb	(revision 331)
+++ EcnlProtoTool/trunk/mruby-2.1.1/mrbgems/mruby-hash-ext/test/hash.rb	(revision 439)
@@ -46,10 +46,4 @@
 end
 
-assert('Hash.try_convert') do
-  assert_nil Hash.try_convert(nil)
-  assert_nil Hash.try_convert("{1=>2}")
-  assert_equal({1=>2}, Hash.try_convert({1=>2}))
-end
-
 assert('Hash#merge!') do
   a = { 'abc_key' => 'abc_value', 'cba_key' => 'cba_value' }
@@ -81,4 +75,18 @@
   h = Hash.new { |hash,k| hash[k] = k }
   assert_equal keys, h.values_at(*keys)
+end
+
+assert('Hash#compact') do
+  h = { "cat" => "feline", "dog" => nil, "cow" => false }
+
+  assert_equal({ "cat" => "feline", "cow" => false }, h.compact)
+  assert_equal({ "cat" => "feline", "dog" => nil, "cow" => false }, h)
+end
+
+assert('Hash#compact!') do
+  h = { "cat" => "feline", "dog" => nil, "cow" => false }
+
+  h.compact!
+  assert_equal({ "cat" => "feline", "cow" => false }, h)
 end
 
@@ -255,2 +263,28 @@
   assert_nil(h.dig(:d))
 end
+
+assert("Hash#transform_keys") do
+  h = {"1" => 100, "2" => 200}
+  assert_equal({"1!" => 100, "2!" => 200},
+               h.transform_keys{|k| k+"!"})
+  assert_equal({1 => 100, 2 => 200},
+               h.transform_keys{|k|k.to_i})
+  assert_same(h, h.transform_keys!{|k|k.to_i})
+  assert_equal({1 => 100, 2 => 200}, h)
+end
+
+assert("Hash#transform_values") do
+  h = {a: 1, b: 2, c: 3}
+  assert_equal({a: 2, b: 5, c: 10},
+               h.transform_values{|v| v * v + 1})
+  assert_equal({a: "1", b: "2", c: "3"},
+               h.transform_values{|v|v.to_s})
+  assert_same(h, h.transform_values!{|v|v.to_s})
+  assert_equal({a: "1", b: "2", c: "3"}, h)
+end
+
+assert("Hash#slice") do
+  h = { a: 100, b: 200, c: 300 }
+  assert_equal({:a=>100}, h.slice(:a))
+  assert_equal({:b=>200, :c=>300}, h.slice(:b, :c, :d))
+end
