Project

General

Profile

Feature #13585

select! and reject! do not returns the same array in specific situations

Added by sobrinho (Gabriel Sobrinho) over 2 years ago. Updated over 2 years ago.

Status:
Rejected
Priority:
Normal
Assignee:
-
Target version:
-
[ruby-core:81294]

Description

When all elements are returned on select!, the method returns nil.

(main) normal> [1,2,3].select! { |x| x == 0 }
=> []
(main) normal> [1,2,3].select! { |x| x == 1 }
=> [1]
(main) normal> [1,2,3].select! { |x| x == 1 || x == 2 }
=> [1, 2]
(main) normal> [1,2,3].select! { |x| x == 1 || x == 2 || x == 3 }
=> nil

When all elements are kept on reject!, nil is returned.

(main) normal> [1,2,3].reject! { |x| x == 0 }
=> nil
(main) normal> [1,2,3].reject! { |x| x == 1 }
=> [2, 3]
(main) normal> [1,2,3].reject! { |x| x == 1 || x == 2 }
=> [3]
(main) normal> [1,2,3].reject! { |x| x == 1 || x == 2 || x == 3 }
=> []

This is surprising since it breaks code in very specific situations that most people won't notice easily:

blocked_assets = relation.to_a.select! { |asset| asset.blocked? }
unblocked_assets = relation.to_a.reject! { |asset| asset.unblocked? }

History

Updated by phluid61 (Matthew Kerwin) over 2 years ago

It's pretty clearly documented:

"If changes were made, it will return self, otherwise it returns nil."

Updated by duerst (Martin Dürst) over 2 years ago

  • Status changed from Open to Rejected

This can be surprising, but it's in line with many other destructive methods. It can be very useful when writing a loop that continues until there's no change anymore. Avoiding destructive methods leads to a better programming style anyway, and in most cases is not slower (because internally, most destructive methods are implemented by copying the actual data (or references) anyway).

Also available in: Atom PDF