Feature #13585
closedselect! and reject! do not returns the same array in specific situations
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? }
Updated by phluid61 (Matthew Kerwin) over 7 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 7 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).
Updated by hsbt (Hiroshi SHIBATA) almost 3 years ago
- Project changed from 14 to Ruby master