RuboCop Performance 1.11 をリリースした。主な変更点は以下。
前者はそのままなので、後者について記す。
Enumerable#filter_map に対応づけられるのは、以下の2つの Cop となる。
これは当初 Performance/FilterMap cop として提案していたものだが、対象となる bad ケースのコンテキストや good ケースとの互換性に違いがあるため、別々の Cop として分割した。
Performance/SelectMap cop
この Cop は select.map のチェーンへのケースを filter_map に置き換えることを提示する。
# bad ary.select(&:foo).map(&:bar) ary.filter(&:foo).map(&:bar) # good ary.filter_map { |o| o.bar if o.foo }
振る舞いに互換性はあるが、good ケースの可読性について賛否があるのと、複雑なブロック処理については自動修正が困難だと思い自動修正を提供しておらず、手修正も大変そうということからデフォルトで無効にしている。
Performance/MapCompact cop
この Cop は map.compact のチェーンへのケースを filter_map に置き換える。このケースは good ケースになることでコードもシンプルになると思う。
# bad ary.map(&:foo).compact ary.collect(&:foo).compact # good ary.filter_map(&:foo)
以下のいずれのケースも nil を除外するが、filter_map は加えて false も除外する。このように compact と filter_map は振る舞いに互換性がないため、SafeAutoCorrect: false (rubocop -A で適用) としている。
[true, false, nil].compact #=> [true, false] [true, false, nil].filter_map(&:itself) #=> [true]
なお、Enumerable#filter_map! というメソッドは存在しないので、以下のケースは受け入れている。
ary.map(&:foo).compact!
Performance/SelectMap cop は好みが分かれるところだと思うが、Performance/MapCompact cop は適用可能であれば適用しておくとコードとしてもシンプルになると思う (ただし振る舞いの違いに気をつけて適材適所で) 。
いつもの新規 Cop のようにデフォルトで pending ステータスなので、NewCops: enable にしているわけでなければ、以下のように有効化が必要となる。
# .rubocop.yml Performance/MapCompact: Enabled: true
今日はここまでです。ハックを続けましょう。