ActiveSupport: alternative Block execution on empty Enumerable

i made a suggestion for this within lighthouse.

Pratik said: "This looks interesting. But I'm not sure if this pattern
belongs to the core or not. You should probably spark a discussion in
the core ML - http://groups.google.com/group/rubyonrails-core"

The Subject can be found here / with a few Pros and Cons...

http://blog.sponagl.de/2009/1/23/alternative-block-execution-on-empty-enumerable

or - the "code only" version:

module Enumerable
  def else(&block)
    self.respond_to?('empty?') && self.empty? ? yield : self
  end
end

Best
Paul

I like it. Is there a ticket and patch that I can verify and add my +1?

Eloy

What about using Object#try and avoiding the explicit &block argument?

This avoid to instantiate a Proc object for each method execution, if any block isn’t passed and the enumerable is empty the VM will raise a LocalJumpError.

module Enumerable

def else

self.try(:empty?) ? yield : self

end

end

Please look at this benchmark (http://gist.github.com/163274) my implementation is exactly 4x faster :wink:

Cheers,

Luca

Similar discussion from an older ticket: https://rails.lighthouseapp.com/projects/8994/tickets/1815-patch-add-or_if_blank-to-object

Yeah creating a proc every time isn’t needed and much cleaner this way. I do think that it’s better to use #blank? as was used in Ryan’s patch. Still waiting for that ticket :slight_smile:

Eloy

Ugh, scrap that, I need sleep.

Ticket: https://rails.lighthouseapp.com/projects/8994/tickets/1950

Mike

Just updated the benchmark (http://gist.github.com/163274), tried to solve the issue using #any? instead of #try, but isn’t fast for filled arrays:

module Enumerable

def else

not any? ? yield : self # don’t try this at home

end

end

Luca

Wouldn't this method be better named "ifempty"? If you call it "else" it makes me wonder where the other part of the clause is? Certainly it reads nicely in expressions like this:

results.each do |x|
   puts x
end.else do
   puts "none found"
end

But each isn't exactly an if statement. I can guess what it means in the context above, but it doesn't read right.

And what if you wanted to use it on its own?

results.else do
   puts "none found"
end

In the case above it makes little sense. "ifempty" seems to read a little better.

… or perhaps even or_if_blank. :slight_smile:

Ryan