April 6, 2021
This blog is part of our Ruby 3.1 series.
We are familiar with the
compact method associated
with arrays. The compact
method returns a copy of the array after removing all
nil
elements.
Ruby 3.1 introduces the compact
method in the Enumerable
module. Now we can
use the compact
method along with the Enumerator
and Enumerator::Lazy
classes which include the Enumerable
module.
=> enum = [1, nil, 3, nil, 5].to_enum
=> #<Enumerator: ...>
=> enum.compact
=> NoMethodError (undefined method `compact' for #<Enumerator: [1, nil, 3, nil, 5]:each>)
=> enum.reject { |x| x.nil? }
=> [1, 3, 5]
=> enum = [1, nil, 3, nil, 5].to_enum
=> #<Enumerator: ...>
=> enum.compact
=> [1, 3, 5]
We can access the compact
method to remove all nil
occurrences from any
classes where we include the Enumerable
module.
class Person
include Enumerable
attr_accessor :names
def initialize(names = [])
@names = names
end
def each &block
@names.each(&block)
end
end
=> list = Person.new(["John", nil, "James", nil])
=> #<Person:0x0000000101cd3de8 @names=["John", nil, "James", nil]>
=> list.compact
=> ["John", "James"]
Similarly, lazy evaluation can be chained with the compact
method to remove
all nil
entries from the Enumerator
collection.
=> enum = [1, nil, 3, nil, 5].to_enum.lazy.compact
=> #<Enumerator::Lazy: ...>
=> enum.force
=> [1, 3, 5]
=> list = Person.new(["John", nil, "James", nil]).lazy.compact
=> #<Enumerator::Lazy: ...>
=> list.force
=> ["John", "James"]
Here's the relevant pull request and feature discussion for this change.
If this blog was helpful, check out our full blog archive.