-
-
Notifications
You must be signed in to change notification settings - Fork 3.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
New Performance/TimesMap cop #2583
Conversation
This should be a performance cop, not a lint cop IMO. |
@bbatsov yep, I agree. Will move it. |
It would be better to squash these 3 commits into 1. There is no need to have a separate commit just to add a line to the changelog. |
@alexdowad sure. I'll squash them when everyone is happy with the changes. Any suggestions on phrasing, tests and everything are welcome :) |
@bbatsov I have relocated the cop to |
# i.to_s | ||
# end | ||
class TimesMap < Cop | ||
MSG = 'Use Array.new with a block instead of .times.map.' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use backticks to highlight the Ruby code (Array.new
and .times.map
).
(When we print out the offense messages, the backticks are removed and the highlighted area is shown in yellow.)
Aside from the minor point mentioned above, this looks good! |
@alexdowad I added backticks and squashed the commits together. |
...and rebased to resolve merge conflicts |
end | ||
end | ||
|
||
context '.times.collect call with a block' do |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems to me you could have generated all 3 tests for both collect
and map
, just to be on the safe side (and to avoid a bit of redundancy).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@bbatsov I added more tests and also fixed the offense message (see my last commit). I leave the commit separate for now so that it is clear what I changed. If everything looks good, let me know - I'll go ahead and squash it into the previous commit.
It checks for calls like this: ``` 9.times.map { |i| f(i) } 5.times.collect(&foo) ``` and suggests using this instead: ``` Array.new(9) { |i| f(i) } Array.new(5, &foo) ```
@alexdowad @bbatsov This PR is ready to merge too. |
It's a new cop introduced by rubocop/rubocop#2583
It's a new cop introduced by rubocop/rubocop#2583
Not all E.g. this uses a starting date to create a series of date ranges going back in time:
I don't particularly want to discuss how good the above code is—I had my reasons for writing it. The main thing is that Rubocop probably shouldn't suggest that Array.new is more correct. |
The point of the performance cops is speed, but your point is valid as well. Seems, however, this is the first problem related to the cop in 5 months. We can limit it just to numeric literals as receivers, but I guess this would reduce its overall usefulness significantly. |
The problem isn't with I've disabled the cop in my project. I understand that I'm an outlier here. |
@kytrinyx Sorry for necroposting, but can you explain how the snippet you've posted can't be replaced with r = new(d.year, d.month)
n.times.map { r = prev(r) }
# it's will result into the same as:
r = new(d.year, d.month)
Array.new(n) { r = prev(r) } |
I don't recall, @ixti. It might be fine like that, I can't remember which project I ran into this was in. |
@kytrinyx thanks! :D Was just pretty curious. |
Constructing an n-element Array where each element is generated by the block is about twice as fast as `n.times.map`[1]. [1] rubocop/rubocop#2583
Constructing an n-element Array where each element is generated by the block is about twice as fast as `n.times.map`[1]. [1] rubocop/rubocop#2583
Constructing an n-element Array where each element is generated by the block is about twice as fast as `n.times.map`[1]. [1] rubocop/rubocop#2583
Constructing an n-element Array where each element is generated by the block is about twice as fast as `n.times.map`[1]. [1] rubocop/rubocop#2583
Constructing an n-element Array where each element is generated by the block is about twice as fast as `n.times.map`[1]. [1] rubocop/rubocop#2583
Constructing an n-element Array where each element is generated by the block is about twice as fast as `n.times.map`[1]. [1] rubocop/rubocop#2583
Constructing an n-element Array where each element is generated by the block is about twice as fast as `n.times.map`[1]. [1] rubocop/rubocop#2583
Constructing an n-element Array where each element is generated by the block is about twice as fast as `n.times.map`[1]. [1] rubocop/rubocop#2583
It checks for calls like this:
and suggests using this instead:
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:
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.