Feature #9867
closedIntroduce each/else block into ruby
Description
Hi
Code like this happens quite often:
if array.any?
array.each do |elem|
some_work
end
else
do_something_else
end
I was thinking if it was possible, to introduce syntax like this:
array.each do |elem|
some_work
else
do_something_else
end
where code in else would fire if array is empty. This would simplify a lot of code nicely and would be completely backwards compatible. Is that a good idea?
Updated by nobu (Nobuyoshi Nakada) almost 10 years ago
- Status changed from Open to Feedback
How would you define else
block for other than Array#each
?
Updated by matz (Yukihiro Matsumoto) almost 10 years ago
We have to define as a whole. If we have introduced your proposal, what should the semantics of a block be?
Or how we could invoke else
part when we define our own each
-like method?
Matz.
Updated by rosenfeld (Rodrigo Rosenfeld Rosas) almost 10 years ago
I'm curious. Personally I don't remember any time I used something like this. Would you mind showing some examples where it happens in your application?
Updated by Killa (Łukasz Strzebińczyk) almost 10 years ago
I came up with this idea after some study on http://handlebarsjs.com/. In that case, the 'else' block is invoked when collection is empty.
This would have clear translation for Array or Hash, however I'm having a problem trying to define this in more global matter.
As for the example, this is quite common case when printing out some collection in erb or any other:
<% if @rooms.any?%>
<% @rooms.each do |room| %>
<%= render "room", room: room %>
<% end %>
<% else %>
There are no rooms created yet. <%= link_to "Create first room!", new_room_path %>
<% end %>
Updated by rosenfeld (Rodrigo Rosenfeld Rosas) almost 10 years ago
Ah, now I see. Indeed it would be useful for templates processing. Since I barely write any ERB those days, that's probably the reason why I never needed something like that... For example, this is how I'd handle those cases usually in my methods:
(do_something_else; return) if array.empty?
array.each {...}
But even this is not that much common in my code. Way more common is the situation where a variable could be even an array or not be present (in which case I'd get nil). In such cases I often write code like:
(hash[:array] || []).each{...}
# or:
Array(hash[:array]).each{...}
But I can definitely see how your proposal would be useful for template languages, like ERB.
It's also interesting to point out that other people seem to be interested on a better approach for handling this case:
Here's one suggested idiom for dealing with it that you might consider:
<% if @messages.each do |message| %>
<%# code or partial to display the message %>
<% end.empty? %>
You have no messages.
<% end %>
Updated by sawa (Tsuyoshi Sawada) almost 10 years ago
Łukasz Strzebińczyk wrote:
... the 'else' block is invoked when collection is empty.
Your proposal is about any?
, but your explanation mentions emptiness, or empty?
, and so the usecase and the proposal do not match. Are you confusing any?
with negation of empty?
? In some cases, the former can be a shorthand for the latter, but they are different.
If your real intention was to condition the first part by the negation of empty?
rather than any?
, then you don't need to condition for the first part as empty array will have nothing to iterate over. It can be simply written as:
array.each do |elem|
some_work
end
unless array.any?
do_something_else
end
Updated by Killa (Łukasz Strzebińczyk) over 9 years ago
Sorry for the delay.
I don't think I am able in specifying it in needed level of detail: (. If that's up to me, the issue can be closed.
Updated by marcandre (Marc-Andre Lafortune) over 6 years ago
- Status changed from Feedback to Closed