each with else

T

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.

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

Robert Dober

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 =3D Order. find:)all)

In view:

<% unless @orders.empty? then %>
<% @orders.each do |order| %>
<%=3D 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| %>
<%=3D 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...
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 m=
e.

Cheers
Robert




--=20
http://ruby-smalltalk.blogspot.com/
 
T

Thorsten Müller

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.
 
R

Robert Klemme

2008/6/11 Thorsten M=FCller said:
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 =3D Order. find:)all)

In view:

<% unless @orders.empty? then %>
<% @orders.each do |order| %>
<%=3D 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| %>
<%=3D 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| %>
<%=3D output order somehow %>
<% end.empty? and begin %>
output message, that there are no orders
<% end %>

or

<% if @orders.each do |order| %>
<%=3D 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 =3D false

each do |item|
found =3D true
yield item
end

found
end
end

and then

<% unless @orders.each_checked do |order| %>
<%=3D output order somehow %>
<% end then %>
output message, that there are no orders
<% end %>

Note: "then" is optional.

Kind regards

robert

--=20
use.inject do |as, often| as.you_can - without end
 
R

Robert Dober

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.


I'd go with Robert's suggestion:

<% @orders.each do |order| %>
<%=3D output order somehow %>
<% end.empty? and begin %>
output message, that there are no orders
<% end %>

or

<% if @orders.each do |order| %>
<%=3D 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 =3D false

each do |item|
found =3D true
yield item
end

found
end
end

and then

<% unless @orders.each_checked do |order| %>
<%=3D output order somehow %>
<% end then %>
output message, that there are no orders
<% end %>

Note: "then" is optional.

Kind regards

robert

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=3Dnil
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





--=20
http://ruby-smalltalk.blogspot.com/
 
T

Thorsten Müller

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? ;)

Yes :) 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...
 
M

Martin DeMello

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
 
R

Rick DeNatale

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


--=20
Rick DeNatale

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

Robert Dober

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

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


--=20
http://ruby-smalltalk.blogspot.com/
 
M

Martin DeMello

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
 
R

Robert Dober

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
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,772
Messages
2,569,591
Members
45,102
Latest member
GregoryGri
Top