In Ruby, we can use Enumerable#map
to process collections. The map
method takes a block:
1
2
3
names = %w(ant)
names.map{ |x| x.upcase }
We can also pass in custom objects which respond to to_proc
:
1
2
3
4
5
6
7
8
class Double
def to_proc
proc{ |n| n * 2 }
end
end
arr = [1.0, 2.0, 3.0]
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
2
3
h = { foo: 1, bar: 2, baz: 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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#/usr/bin/env ruby
require "benchmark/ips"
arr = [1.0, 2.0, 3.0]
h = { foo: 1, bar: 2, baz: 3 }
class Double
def to_proc
proc{ |n| n * 2 }
end
end
Benchmark.ips do |x|
x.report("arr.map{ |x| x*2 }"){
arr.map{ |x| x*2 }
}
x.report("arr.map(&Double.new)"){
arr.map(&Double.new)
}
x.report("[:foo, :bar].map"){
[:foo, :bar].map{ |x| h[x] }
}
x.report("[:foo, :bar].map(&h)"){
[:foo, :bar].map(&h)
}
x.compare!
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!!