Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does RuboCop suggest replacing .times.map with Array.new?

RuboCop suggests:

Use Array.new with a block instead of .times.map.

In the docs for the cop:

This cop checks for .times.map calls. In most cases such calls can be replaced with an explicit array creation.

Examples:

# bad 9.times.map do |i|   i.to_s end  # good Array.new(9) do |i|   i.to_s end 

I know it can be replaced, but I feel 9.times.map is closer to English grammar, and it's easier to understand what the code does.

Why should it be replaced?

like image 741
shirakia Avatar asked Jan 07 '17 07:01

shirakia


1 Answers

The latter is more performant; here is an explanation: Pull request where this cop was added

It checks for calls like this:

9.times.map { |i| f(i) } 9.times.collect(&foo) 

and suggests using this instead:

Array.new(9) { |i| f(i) } Array.new(9, &foo) 

The new code has approximately the same size, but uses fewer method calls, consumes less memory, works a tiny bit faster and in my opinion is more readable.

I've seen many occurrences of times.{map,collect} in different well-known projects: Rails, GitLab, Rubocop and several closed-source apps.

Benchmarks:

Benchmark.ips do |x|   x.report('times.map') { 5.times.map{} }   x.report('Array.new') { Array.new(5){} }   x.compare! end __END__ Calculating -------------------------------------            times.map    21.188k i/100ms            Array.new    30.449k i/100ms -------------------------------------------------            times.map    311.613k (± 3.5%) i/s -      1.568M            Array.new    590.374k (± 1.2%) i/s -      2.954M  Comparison:            Array.new:   590373.6 i/s            times.map:   311612.8 i/s - 1.89x slower 

I'm not sure now that Lint is the correct namespace for the cop. Let me know if I should move it to Performance.

Also I didn't implement autocorrection because it can potentially break existing code, e.g. if someone has Fixnum#times method redefined to do something fancy. Applying autocorrection would break their code.

like image 173
mikdiet Avatar answered Oct 06 '22 23:10

mikdiet