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 slowerFrom 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!!