summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorYukihiro "Matz" Matsumoto <[email protected]>2014-09-19 00:36:33 +0900
committerYukihiro "Matz" Matsumoto <[email protected]>2014-09-19 00:36:33 +0900
commit02b2ac8de2ea12b97bc80aab0d582cda4634e71c (patch)
tree91564b430a63534d98166b3200efb04d34777838
parente4bd48f3f724216ee1a8e77ad1afb2e1dae79099 (diff)
parent5f16c41753f7789065f2c2bfe84395cad8cadcaa (diff)
downloadmruby-02b2ac8de2ea12b97bc80aab0d582cda4634e71c.tar.gz
mruby-02b2ac8de2ea12b97bc80aab0d582cda4634e71c.zip
Merge pull request #2594 from yasuyuki/hash
Implement Hash[]
-rw-r--r--mrbgems/mruby-hash-ext/mrblib/hash.rb52
-rw-r--r--mrbgems/mruby-hash-ext/test/hash.rb38
2 files changed, 90 insertions, 0 deletions
diff --git a/mrbgems/mruby-hash-ext/mrblib/hash.rb b/mrbgems/mruby-hash-ext/mrblib/hash.rb
index 9da08dc3a..f214cb1d5 100644
--- a/mrbgems/mruby-hash-ext/mrblib/hash.rb
+++ b/mrbgems/mruby-hash-ext/mrblib/hash.rb
@@ -5,6 +5,58 @@ class Hash
##
# call-seq:
+ # Hash[ key, value, ... ] -> new_hash
+ # Hash[ [ [key, value], ... ] ] -> new_hash
+ # Hash[ object ] -> new_hash
+ #
+ # Creates a new hash populated with the given objects.
+ #
+ # Similar to the literal <code>{ _key_ => _value_, ... }</code>. In the first
+ # form, keys and values occur in pairs, so there must be an even number of
+ # arguments.
+ #
+ # The second and third form take a single argument which is either an array
+ # of key-value pairs or an object convertible to a hash.
+ #
+ # Hash["a", 100, "b", 200] #=> {"a"=>100, "b"=>200}
+ # Hash[ [ ["a", 100], ["b", 200] ] ] #=> {"a"=>100, "b"=>200}
+ # Hash["a" => 100, "b" => 200] #=> {"a"=>100, "b"=>200}
+ #
+
+ def self.[](*object)
+ o = object[0]
+ if o.respond_to?(:to_hash)
+ h = Hash.new
+ object[0].to_hash.each { |k, v| h[k] = v }
+ return h
+ elsif o.respond_to?(:to_a)
+ h = Hash.new
+ o.to_a.each do |i|
+ raise ArgumentError, "wrong element type #{i.class} (expected array)" unless i.respond_to?(:to_a)
+ k, v = nil
+ case i.size
+ when 2
+ k = i[0]
+ v = i[1]
+ when 1
+ k = i[0]
+ else
+ raise ArgumentError, "invalid number of elements (#{i.size} for 1..2)"
+ end
+ h[k] = v
+ end
+ return h
+ end
+ raise ArgumentError, 'odd number of arguments for Hash' unless object.length % 2 == 0
+ h = Hash.new
+ 0.step(object.length - 2, 2) do |i|
+ h[object[i]] = object[i + 1]
+ end
+ h
+ end
+
+ ##
+ # call-seq:
# hsh.merge!(other_hash) -> hsh
# hsh.merge!(other_hash){|key, oldval, newval| block} -> hsh
#
diff --git a/mrbgems/mruby-hash-ext/test/hash.rb b/mrbgems/mruby-hash-ext/test/hash.rb
index 2bc5b911a..e1afdaaa3 100644
--- a/mrbgems/mruby-hash-ext/test/hash.rb
+++ b/mrbgems/mruby-hash-ext/test/hash.rb
@@ -1,6 +1,44 @@
##
# Hash(Ext) Test
+assert('Hash.[] Hash') do
+ a = Hash['a_key' => 'a_value']
+
+ assert_equal({'a_key' => 'a_value'}, a)
+end
+
+assert('Hash.[] [ [ ["b_key", "b_value" ] ] ]') do
+ a = Hash[ [ ['b_key', 'b_value'] ] ]
+
+ assert_equal({'b_key' => 'b_value'}, a)
+
+ a = Hash[ [ ] ]
+
+ assert_equal({}, a)
+
+ assert_raise(ArgumentError) do
+ Hash[ [ ['b_key', 'b_value', 'b_over'] ] ]
+ end
+
+ assert_raise(ArgumentError) do
+ Hash[ [ [] ] ]
+ end
+end
+
+assert('Hash.[] "c_key", "c_value"') do
+ a = Hash['c_key', 'c_value', 'd_key', 1]
+
+ assert_equal({'c_key' => 'c_value', 'd_key' => 1}, a)
+
+ a = Hash[]
+
+ assert_equal({}, a)
+
+ assert_raise(ArgumentError) do
+ Hash['d_key']
+ end
+end
+
assert('Hash#merge!') do
a = { 'abc_key' => 'abc_value', 'cba_key' => 'cba_value' }
b = { 'cba_key' => 'XXX', 'xyz_key' => 'xyz_value' }