[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

each with else

Thorsten Müller

6/11/2008 9:10:00 AM

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...
10 Answers

Robert Dober

6/11/2008 10:38:00 AM

0

On Wed, Jun 11, 2008 at 11:09 AM, Thorsten M=FCller <thorsten@80beans.com> =
wrote:
> 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.blo...

---
As simple as possible, but not simpler.
Albert Einstein

Thorsten Müller

6/11/2008 11:27:00 AM

0

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.

Robert Klemme

6/11/2008 11:41:00 AM

0

2008/6/11 Thorsten M=FCller <thorsten@80beans.com>:
> 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

Robert Dober

6/11/2008 3:37:00 PM

0

On Wed, Jun 11, 2008 at 1:41 PM, Robert Klemme
<shortcutter@googlemail.com> wrote:
> 2008/6/11 Thorsten M=FCller <thorsten@80beans.com>:
>> 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
>
> --
> 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=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.blo...

---
As simple as possible, but not simpler.
Albert Einstein

Thorsten Müller

6/11/2008 4:52:00 PM

0

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

Martin DeMello

6/11/2008 5:19:00 PM

0

On Wed, Jun 11, 2008 at 9:54 AM, Thorsten M=FCller <thorsten@80beans.com> w=
rote:
>
> 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

Rick DeNatale

6/11/2008 6:18:00 PM

0

On Wed, Jun 11, 2008 at 12:54 PM, Thorsten M=FCller <thorsten@80beans.com>
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.denh...articles/2008/05/21/what-would-...
if-you-had-to-stop-using-ruby-and-go-back-to-smalltalk


--=20
Rick DeNatale

My blog on Ruby
http://talklikeaduck.denh...

Robert Dober

6/11/2008 6:19:00 PM

0

On Wed, Jun 11, 2008 at 7:19 PM, Martin DeMello <martindemello@gmail.com> w=
rote:
> On Wed, Jun 11, 2008 at 9:54 AM, Thorsten M=FCller <thorsten@80beans.com>=
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
>
>

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

---
As simple as possible, but not simpler.
Albert Einstein

Martin DeMello

6/11/2008 6:23:00 PM

0

On Wed, Jun 11, 2008 at 11:18 AM, Robert Dober <robert.dober@gmail.com> 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

Robert Dober

6/11/2008 6:31:00 PM

0

On Wed, Jun 11, 2008 at 8:23 PM, Martin DeMello <martindemello@gmail.com> wrote:
> On Wed, Jun 11, 2008 at 11:18 AM, Robert Dober <robert.dober@gmail.com> 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.blo...

---
As simple as possible, but not simpler.
Albert Einstein