Each with else

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.

Please give your opinions to that idea and if you think
there would be a chance to get this implemented one day…

Hi Robert,

thanks for your reply.

But in fact this should be the first step in direction of a RCR.

The problem can be solved easy enough, as the first example shows.
The idea with the else clause would only make the code more readable.

So I consider to write a RCR, but want to hear more opinions,
especially since my Ruby experience is only working one year
with Rails by now.

On Wed, Jun 11, 2008 at 11:09 AM, Thorsten Müller [email protected]
wrote:

@orders = Order. find(:all)

I guess, that would be true for any other Ruby code, too.

Please give your opinions to that idea and if you think
there would be a chance to get this implemented one day…

Hmmm maybe you should use map than

As you claimed that this is a Ruby issue I will not write Rails code
here

@orders.map{ |order| whatever }.empty? and puts “there are no orders”

I know map with side effects is maybe a little bit counterproductive
for readability and maintenance but in order to use each you have to
enhance Enumerable first.

module Enumerable
def empty?; first > last end
end

@orders.each{ |order| … }.empty? and …

but honestly would it not be better to write

if @orders.empty? then
else
end
?

BTW the implementation of Enumerable#empty? looks much more like a RCR
to me.

Cheers
Robert


http://ruby-smalltalk.blogspot.com/


As simple as possible, but not simpler.
Albert Einstein

2008/6/11 Thorsten Müller [email protected]:

@orders = Order. find(:all)

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

On Wed, Jun 11, 2008 at 1:41 PM, Robert K.
[email protected] wrote:

<% end %>

because it is inside the block. This is something you clearly do
output message, that there are no orders
Note that depending on the type of @orders you do not even need to
end
output message, that there are no orders

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 :wink:

Guess that this is pretty much what OP wants, right? :wink:

Cheers
Robert


http://ruby-smalltalk.blogspot.com/


As simple as possible, but not simpler.
Albert Einstein

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 :wink:

Guess that this is pretty much what OP wants, right? :wink:

Yes :slight_smile: That would be something in the right direction.
My first thought was to propose something like that for Rails only.
But then I thought that the plain form with a “full” else would
give us a cleaner syntax.

Funny that you mention smalltalk. I don’t know much about it, but
remember to have read a discussion about it’s pure oop and that you
can handle even core language features like if/then/else like any
other class.
This would be an example where it would be handy to have it.

hmmmm, maybe the RCR should be even more comprehensive and
request for a completely new language construct that would allow
to built new core commands, based on multiple blocks.
Not only if/then, but case/when also.

But that’s too much for now, a new each would be enough…

On Wed, Jun 11, 2008 at 9:54 AM, Thorsten Müller [email protected]
wrote:

hmmmm, maybe the RCR should be even more comprehensive and
request for a completely new language construct that would allow
to built new core commands, based on multiple blocks.
Not only if/then, but case/when also.

But that’s too much for now, a new each would be enough…

More simply, you can define an Object#if_empty

class Object
def if_empty
yield if self.empty?
end
end

a.each {|x| do something}.if_empty { do something else }

this relies on the fact that obj#each returns obj.

martin

On Wed, Jun 11, 2008 at 7:19 PM, Martin DeMello
[email protected] wrote:

martin

Martin I think you did not read my reply reagrding this technique, it
is funny though that you want to define Object#is_empty, I would say
that the Ruby way would be Object#empty?

I gave an implementation for Enumerable#empty? using #last, this was
an error because there is no Enumerable#last, I tested with Range
only.

But the point is that I started to think about “emptiness” as a concept.
The first idea was

class Object
def empty?; instance_variables.all?{ |ivar| instance_variable_get(
ivar ).nil? } end
end

now one needs to redefine empty? for all classes including Enumerable
of course, because to_a.empty is simply not an option of course. But I
am sure that emptiness might be a concept that could be generalized
from arrays and hashes.

Cheers
Robert


http://ruby-smalltalk.blogspot.com/


As simple as possible, but not simpler.
Albert Einstein

On Wed, Jun 11, 2008 at 12:54 PM, Thorsten Müller [email protected]
wrote:

Funny that you mention smalltalk. I don’t know much about it, but
remember to have read a discussion about it’s pure oop and that you
can handle even core language features like if/then/else like any
other class.
This would be an example where it would be handy to have it.

Although it’s true that you can define additional control flow in
Smalltalk
using methods and blocks is true, it’s a bit of a myth that the basic
control flow is really implemented that way:

http://talklikeaduck.denhaven2.com/articles/2008/05/21/what-would-you-miss-if-you-had-to-stop-using-ruby-and-go-back-to-smalltalk


Rick DeNatale

My blog on Ruby
http://talklikeaduck.denhaven2.com/

On Wed, Jun 11, 2008 at 8:23 PM, Martin DeMello
[email protected] wrote:

On Wed, Jun 11, 2008 at 11:18 AM, Robert D. [email protected] wrote:

Martin I think you did not read my reply reagrding this technique, it
is funny though that you want to define Object#is_empty, I would say
that the Ruby way would be Object#empty?

I did - mine is different in that it doesn’t require explicit use of
the built-in control structures like if/else or and

Indeed you did!! I only now grasp your concept, very nice indeed :).
Sorry should have known you better, we can of course emulate things like
if_true, if_nil, unless_fourtytwo (well that one is a joke ).

But I guess we are getting too Smalltalkish here, Ruby shall remain
Ruby, but we can play with it as much as we want.

Cheers
Robert


http://ruby-smalltalk.blogspot.com/


As simple as possible, but not simpler.
Albert Einstein

On Wed, Jun 11, 2008 at 11:18 AM, Robert D. [email protected]
wrote:

Martin I think you did not read my reply reagrding this technique, it
is funny though that you want to define Object#is_empty, I would say
that the Ruby way would be Object#empty?

I did - mine is different in that it doesn’t require explicit use of
the built-in control structures like if/else or and

I gave an implementation for Enumerable#empty? using #last, this was
an error because there is no Enumerable#last, I tested with Range
only.

But the point is that I started to think about “emptiness” as a concept.

Yep, I was exploring the other half of the coin - how to make the most
convenient use of empty? once defined.

martin