In Ruby, we can use Enumerable#map
to process collections. The map
method takes a block:
1 names = %w(ant)
2
3 names.map{ |x| x.upcase }
We can also pass in custom objects which respond to to_proc
:
1 class Double
2 def to_proc
3 proc{ |n| n * 2 }
4 end
5 end
6
7 arr = [1.0, 2.0, 3.0]
8 arr.map(&Double.new) # => [2.0, 4.0, 6.0]
In Ruby 2.3+, Hash
has a to_proc
method which means we can pass a hash into a collection:
1 h = { foo: 1, bar: 2, baz: 3 }
2
3 [:foo, :bar].map(&h) #=> calls h.to_proc
I decided to do a quick benchmark on how efficient the block method of map runs compared to the using a proc:
The results show that using proc
is slower than calling map
with a block:
1 #/usr/bin/env ruby
2
3 require "benchmark/ips"
4
5 arr = [1.0, 2.0, 3.0]
6
7 h = { foo: 1, bar: 2, baz: 3 }
8
9 class Double
10 def to_proc
11 proc{ |n| n * 2 }
12 end
13 end
14
15 Benchmark.ips do |x|
16 x.report("arr.map{ |x| x*2 }"){
17 arr.map{ |x| x*2 }
18 }
19
20 x.report("arr.map(&Double.new)"){
21 arr.map(&Double.new)
22 }
23
24 x.report("[:foo, :bar].map"){
25 [:foo, :bar].map{ |x| h[x] }
26 }
27
28 x.report("[:foo, :bar].map(&h)"){
29 [:foo, :bar].map(&h)
30 }
31
32 x.compare!
33 end
Warming up --------------------------------------
arr.map{ |x| x*2 } 94.558k i/100ms
arr.map(&Double.new) 40.587k i/100ms
[:foo, :bar].map 111.149k i/100ms
[:foo, :bar].map(&h) 71.085k i/100ms
Calculating -------------------------------------
arr.map{ |x| x*2 } 1.740M (± 5.6%) i/s - 8.699M in 5.015954s
arr.map(&Double.new) 591.703k (± 5.8%) i/s - 2.963M in 5.024683s
[:foo, :bar].map 1.919M (±15.7%) i/s - 9.225M in 5.049601s
[:foo, :bar].map(&h) 995.047k (±15.0%) i/s - 4.834M in 5.029552s
Comparison:
[:foo, :bar].map: 1919075.6 i/s
arr.map{ |x| x*2 }: 1739722.6 i/s - same-ish: difference falls within error
[:foo, :bar].map(&h): 995046.9 i/s - 1.93x slower
arr.map(&Double.new): 591703.4 i/s - 3.24x slower
From the results, I learnt that using dynamic procs may be more suited for smaller collections with map
. For larger collections, it is more efficient to stick to the block method.
Happy Hacking and stay curious!!