From: Robert Dober Date: 2008-06-12T00:36:44+09:00 Subject: Re: each with else On Wed, Jun 11, 2008 at 1:41 PM, Robert Klemme wrote: > 2008/6/11 Thorsten Müller : >> Hi all, >> >> that's just an idea I came up with and thought worth a discussion. >> >> Would it be possible to give each an else part? >> >> For Rails programmers it is very common to do something like this: >> >> In controller search for records: >> >> @orders = Order. find(:all) >> >> In view: >> >> <% unless @orders.empty? then %> >> <% @orders.each do |order| %> >> <%= output order somehow %> >> <% end %> >> <% else %> >> output message, that there are no orders >> <% end %> >> >> If each would have it's own else which runs if the >> used array, enumerable or whatever is empty, >> that code could look much nicer: >> >> <% @orders.each do |order| %> >> <%= output order somehow %> >> <% else %> >> output message, that there are no orders >> <% end %> >> >> I guess, that would be true for any other Ruby code, too. > > No. This does not work because your bit translates to > > @orders.each do |order| > # output order somehow expression > else > end > > This would mean that the "else" branch is executed for each iteration > because it is *inside* the block. This is something you clearly do > not want. > >> Please give your opinions to that idea and if you think >> there would be a chance to get this implemented one day... > > I'd go with Robert's suggestion: > > <% @orders.each do |order| %> > <%= output order somehow %> > <% end.empty? and begin %> > output message, that there are no orders > <% end %> > > or > > <% if @orders.each do |order| %> > <%= output order somehow %> > <% end.empty? %> > output message, that there are no orders > <% end %> > > Note that depending on the type of @orders you do not even need to > define #empty? (Array and Hash have it). If there are special types > you could do > > module Enumerable > def each_checked > found = false > > each do |item| > found = true > yield item > end > > found > end > end > > and then > > <% unless @orders.each_checked do |order| %> > <%= output order somehow %> > <% end then %> > output message, that there are no orders > <% end %> > > Note: "then" is optional. > > Kind regards > > robert > > -- > use.inject do |as, often| as.you_can - without end > > This is one of the cases where the elegance of Smalltalk shines, you would simply write something like ary eachDo: [ :ele | ... ] orIfEmpty: [ whateverElse ] makes me wanting Eric's patch for the simplified lambda syntax even more, than we can write in pure Ruby module Enumerable def each_else each_blk, else_blk=nil return else_blk && else_blk.call if empty? each &each_blk end end and we could call it with ary.each_else do | ele | puts ele end, do puts "empty" end or ary.each_else {|ele| puts ele }, {|| puts "empty" } without having checked for precedence, maybe some "()" are needed ;) Guess that this is pretty much what OP wants, right? ;) Cheers Robert -- http://ruby-smalltalk.blogspot.com/ --- As simple as possible, but not simpler. Albert Einstein