Skip to content

Commit ca0c802

Browse files
committed
Refactor {Hash, Array, Enumerable, Struct , ENV}#to_h methods and extract processing of returned by a block value into a helper method
1 parent 9718271 commit ca0c802

File tree

10 files changed

+79
-56
lines changed

10 files changed

+79
-56
lines changed

spec/ruby/core/array/to_h_spec.rb

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,12 @@
4545
[:a, :b].to_h { |k| [k, k.to_s] }.should == { a: 'a', b: 'b' }
4646
end
4747

48+
it "passes to a block each element as a single argument" do
49+
ScratchPad.record []
50+
[[:a, 1], [:b, 2]].to_h { |*args| ScratchPad << args; [args[0], args[1]] }
51+
ScratchPad.recorded.sort.should == [[[:a, 1]], [[:b, 2]]]
52+
end
53+
4854
it "raises ArgumentError if block returns longer or shorter array" do
4955
-> do
5056
[:a, :b].to_h { |k| [k, k.to_s, 1] }

spec/ruby/core/enumerable/to_h_spec.rb

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,14 @@ def enum.each(*args)
5353
@enum.to_h { |k| [k, k.to_s] }.should == { a: 'a', b: 'b' }
5454
end
5555

56+
it "passes to a block each element as a single argument" do
57+
enum_of_arrays = EnumerableSpecs::EachDefiner.new([:a, 1], [:b, 2])
58+
59+
ScratchPad.record []
60+
enum_of_arrays.to_h { |*args| ScratchPad << args; [args[0], args[1]] }
61+
ScratchPad.recorded.sort.should == [[[:a, 1]], [[:b, 2]]]
62+
end
63+
5664
it "raises ArgumentError if block returns longer or shorter array" do
5765
-> do
5866
@enum.to_h { |k| [k, k.to_s, 1] }

spec/ruby/core/env/to_h_spec.rb

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,18 @@
1818
ENV.to_h { |k, v| [k, v.upcase] }.should == { 'a' => "B", 'c' => "D" }
1919
end
2020

21+
it "passes to a block each pair's key and value as separate arguments" do
22+
ENV.replace("a" => "b", "c" => "d")
23+
24+
ScratchPad.record []
25+
ENV.to_h { |k, v| ScratchPad << [k, v]; [k, v] }
26+
ScratchPad.recorded.sort.should == [["a", "b"], ["c", "d"]]
27+
28+
ScratchPad.record []
29+
ENV.to_h { |*args| ScratchPad << args; [args[0], args[1]] }
30+
ScratchPad.recorded.sort.should == [["a", "b"], ["c", "d"]]
31+
end
32+
2133
it "does not require the array elements to be strings" do
2234
ENV.replace("a" => "b", "c" => "d")
2335
ENV.to_h { |k, v| [k.to_sym, v.to_sym] }.should == { :a => :b, :c => :d }

spec/ruby/core/struct/to_h_spec.rb

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,18 @@
2121
h.should == { "make" => "ford", "model" => "ranger", "year" => "" }
2222
end
2323

24+
it "passes to a block each pair's key and value as separate arguments" do
25+
s = StructClasses::Ruby.new('3.2.4', 'macos')
26+
27+
ScratchPad.record []
28+
s.to_h { |k, v| ScratchPad << [k, v]; [k, v] }
29+
ScratchPad.recorded.sort.should == [[:platform, 'macos'], [:version, '3.2.4']]
30+
31+
ScratchPad.record []
32+
s.to_h { |*args| ScratchPad << args; [args[0], args[1]] }
33+
ScratchPad.recorded.sort.should == [[:platform, 'macos'], [:version, '3.2.4']]
34+
end
35+
2436
it "raises ArgumentError if block returns longer or shorter array" do
2537
-> do
2638
StructClasses::Car.new.to_h { |k, v| [k.to_s, "#{v}".downcase, 1] }

src/main/ruby/truffleruby/core/array.rb

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1296,19 +1296,10 @@ def to_ary
12961296
end
12971297

12981298
def to_h
1299-
h = Hash.new
1299+
h = {}
13001300
each_with_index do |elem, i|
13011301
elem = yield(elem) if block_given?
1302-
unless elem.respond_to?(:to_ary)
1303-
raise TypeError, "wrong element type #{Primitive.class(elem)} at #{i} (expected array)"
1304-
end
1305-
1306-
ary = elem.to_ary
1307-
if ary.size != 2
1308-
raise ArgumentError, "wrong array length at #{i} (expected 2, was #{ary.size})"
1309-
end
1310-
1311-
h[ary[0]] = ary[1]
1302+
Truffle::HashOperations.assoc_key_value_pair_with_position(h, elem, i)
13121303
end
13131304
h
13141305
end

src/main/ruby/truffleruby/core/enumerable.rb

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -319,16 +319,7 @@ def to_h(*args)
319319
each(*args) do
320320
elem = Primitive.single_block_arg
321321
elem = yield(elem) if block_given?
322-
unless elem.respond_to?(:to_ary)
323-
raise TypeError, "wrong element type #{Primitive.class(elem)} (expected array)"
324-
end
325-
326-
ary = elem.to_ary
327-
if ary.size != 2
328-
raise ArgumentError, "element has wrong array length (expected 2, was #{ary.size})"
329-
end
330-
331-
h[ary[0]] = ary[1]
322+
Truffle::HashOperations.assoc_key_value_pair(h, elem)
332323
end
333324
h
334325
end

src/main/ruby/truffleruby/core/env.rb

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -286,18 +286,9 @@ def to_h
286286
return to_hash unless block_given?
287287

288288
h = {}
289-
each_pair do |*elem|
290-
elem = yield(elem)
291-
unless elem.respond_to?(:to_ary)
292-
raise TypeError, "wrong element type #{Primitive.class(elem)} (expected array)"
293-
end
294-
295-
ary = elem.to_ary
296-
if ary.size != 2
297-
raise ArgumentError, "element has wrong array length (expected 2, was #{ary.size})"
298-
end
299-
300-
h[ary[0]] = ary[1]
289+
each_pair do |k, v|
290+
pair = yield(k, v)
291+
Truffle::HashOperations.assoc_key_value_pair(h, pair)
301292
end
302293
h
303294
end

src/main/ruby/truffleruby/core/hash.rb

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -357,17 +357,8 @@ def to_h
357357
if block_given?
358358
h = {}
359359
each do |k, v|
360-
elem = yield(k, v)
361-
unless elem.respond_to?(:to_ary)
362-
raise TypeError, "wrong element type #{Primitive.class(elem)} (expected array)"
363-
end
364-
365-
ary = elem.to_ary
366-
if ary.size != 2
367-
raise ArgumentError, "element has wrong array length (expected 2, was #{ary.size})"
368-
end
369-
370-
h[ary[0]] = ary[1]
360+
pair = yield(k, v)
361+
Truffle::HashOperations.assoc_key_value_pair(h, pair)
371362
end
372363
h
373364
elsif instance_of? Hash

src/main/ruby/truffleruby/core/struct.rb

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -109,18 +109,9 @@ def select
109109

110110
def to_h
111111
h = {}
112-
each_pair.each_with_index do |elem, i|
113-
elem = yield(elem) if block_given?
114-
unless elem.respond_to?(:to_ary)
115-
raise TypeError, "wrong element type #{Primitive.class(elem)} at #{i} (expected array)"
116-
end
117-
118-
ary = elem.to_ary
119-
if ary.size != 2
120-
raise ArgumentError, "element has wrong array length (expected 2, was #{ary.size})"
121-
end
122-
123-
h[ary[0]] = ary[1]
112+
each_pair do |k, v|
113+
pair = block_given? ? yield(k, v) : [k, v]
114+
Truffle::HashOperations.assoc_key_value_pair(h, pair)
124115
end
125116
h
126117
end

src/main/ruby/truffleruby/core/truffle/hash_operations.rb

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,5 +17,35 @@ def self.hash_merge(current, other)
1717
end
1818
new_hash
1919
end
20+
21+
# MRI: rb_hash_set_pair (rb_ary_to_h also contains similar logic for Array#to_h)
22+
def self.assoc_key_value_pair(hash, pair)
23+
ary = Truffle::Type.rb_check_convert_type pair, Array, :to_ary
24+
25+
unless ary
26+
raise TypeError, "wrong element type #{Primitive.class(pair)} (expected array)"
27+
end
28+
29+
if ary.size != 2
30+
raise ArgumentError, "element has wrong array length (expected 2, was #{ary.size})"
31+
end
32+
33+
hash[ary[0]] = ary[1]
34+
end
35+
36+
# MRI: extracted from rb_ary_to_h, is similar to rb_hash_set_pair
37+
def self.assoc_key_value_pair_with_position(hash, pair, index)
38+
ary = Truffle::Type.rb_check_convert_type pair, Array, :to_ary
39+
40+
unless ary
41+
raise TypeError, "wrong element type #{Primitive.class(pair)} at #{index} (expected array)"
42+
end
43+
44+
if ary.size != 2
45+
raise ArgumentError, "wrong array length at #{index} (expected 2, was #{ary.size})"
46+
end
47+
48+
hash[ary[0]] = ary[1]
49+
end
2050
end
2151
end

0 commit comments

Comments
 (0)