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.