Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
221 views
in Technique[技术] by (71.8m points)

ruby - 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?

question from:https://stackoverflow.com/questions/41518896/why-does-rubocop-suggest-replacing-times-map-with-array-new

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...