[lnkForumImage]
TotalShareware - Download Free Software

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


 

Forums >

comp.lang.ruby

Re: Syntax sugar idea for loops

Berger, Daniel

3/30/2005 7:23:00 PM

> -----Original Message-----
> From: pmak@aaanime.net [mailto:pmak@aaanime.net]
> Sent: Wednesday, March 30, 2005 11:30 AM
> To: ruby-talk ML
> Subject: Syntax sugar idea for loops
>
>
> I was working with a proprietary programming language called
> Traction <www.tractionsoftware.com>, and I noticed something
> pretty cool they had in their loop constructs.
>
> Consider the following Ruby code:
>
> every_other = true
> people.each do |person|
> every_other = !every_other
> row_class = every_other ? 'row1' : 'row2'
> puts "<tr class=#{row_class}><td>#{person.name}</td>
> <td>#{person.email}</td></tr>"
> end
>
> This code prints out an HTML table of peoples' names and
> e-mail addresses. The <tr> tags alternate with having
> class="row1" and class="row2", allowing every other row to be
> colored differently.
>
> Consider these two lines of the code, though:
>
> every_other = true
> every_other = !every_other
>
> These lines could be replaced by syntax sugar. Traction has
> the following "Special Loop Tags":
>
> <loop.first>: true if this is the first iteration of the loop
> <loop.inner> true if this is not the first or last
> iteration of the loop
> <loop.odd> true if this is an odd iteration
> <loop.last>: true if this is the last iteration of the loop
>
> (In the case of nested loops, they apply to the innermost
> loop.) Maybe Ruby could use this sort of syntax sugar, too?
> So in my example above, there would be a built-in variable
> that replaces my "every_other" variable.

I think Enumerable#each_with_index largely eliminates the need for such
syntactic sugar. Consider:

people.each_with_index do |person, i|
puts "First person: #{person}" if i == 0
row_class = i%2 == 0 ? "row1" : "row2"
puts "<tr class=#{row_class}><td>#{person.name}</td>
puts "Last person: #{person}" if i == people.length - 1
end

I suppose you could extend Fixnum within a loop to include extra methods
so that you could do something like this:

people.each_with_index do |person, i|
puts "First person: #{person} if i.first?
row_class = i.even? ? "row1" : "row2"
puts "Last person: #{person} if i.last?
end

But that would mean making some serious modifications to Enumerable
(wouldn't it?). Not a bad idea, just not worth the added code
maintenance IMHO.

Regards,

Dan




11 Answers

Eric Hodel

3/30/2005 7:38:00 PM

0

On 30 Mar 2005, at 11:23, Berger, Daniel wrote:

>> From: pmak@aaanime.net [mailto:pmak@aaanime.net]
>>
>> Consider the following Ruby code:
>>
>> every_other = true
>> people.each do |person|
>> every_other = !every_other
>> row_class = every_other ? 'row1' : 'row2'
>> puts "<tr class=#{row_class}><td>#{person.name}</td>
>> <td>#{person.email}</td></tr>"
>> end
>>
>> Consider these two lines of the code, though:
>>
>> every_other = true
>> every_other = !every_other
>>
>> These lines could be replaced by syntax sugar. Traction has
>> the following "Special Loop Tags":
>>
>> <loop.first>: true if this is the first iteration of the loop
>> <loop.inner> true if this is not the first or last
>> iteration of the loop
>> <loop.odd> true if this is an odd iteration
>> <loop.last>: true if this is the last iteration of the loop
>
> I think Enumerable#each_with_index largely eliminates the need for such
> syntactic sugar. Consider:
>
> people.each_with_index do |person, i|
> puts "First person: #{person}" if i == 0
> row_class = i%2 == 0 ? "row1" : "row2"
> puts "<tr class=#{row_class}><td>#{person.name}</td>
> puts "Last person: #{person}" if i == people.length - 1
> end
>
> I suppose you could extend Fixnum within a loop to include extra
> methods
> so that you could do something like this:

people.each_with_index do |person, i|
puts "First person: #{person} if person == people.first
row_class = i.even? ? "row1" : "row2"
puts "Last person: #{person} if person == people.last
end

How about that?

--
Eric Hodel - drbrain@segment7.net - http://se...
FEC2 57F1 D465 EB15 5D6E 7C11 332A 551C 796C 9F04



Patrick Hurley

3/30/2005 7:51:00 PM

0

On Thu, 31 Mar 2005 04:37:42 +0900, Eric Hodel <drbrain@segment7.net> wrote:
> On 30 Mar 2005, at 11:23, Berger, Daniel wrote:
>
> >> From: pmak@aaanime.net [mailto:pmak@aaanime.net]
> >>
> >> Consider the following Ruby code:
> >>
> >> every_other = true
> >> people.each do |person|
> >> every_other = !every_other
> >> row_class = every_other ? 'row1' : 'row2'
> >> puts "<tr class=#{row_class}><td>#{person.name}</td>
> >> <td>#{person.email}</td></tr>"
> >> end
> >>
> >> Consider these two lines of the code, though:
> >>
> >> every_other = true
> >> every_other = !every_other
> >>
> >> These lines could be replaced by syntax sugar. Traction has
> >> the following "Special Loop Tags":
> >>
> >> <loop.first>: true if this is the first iteration of the loop
> >> <loop.inner> true if this is not the first or last
> >> iteration of the loop
> >> <loop.odd> true if this is an odd iteration
> >> <loop.last>: true if this is the last iteration of the loop
> >
> > I think Enumerable#each_with_index largely eliminates the need for such
> > syntactic sugar. Consider:
> >
> > people.each_with_index do |person, i|
> > puts "First person: #{person}" if i == 0
> > row_class = i%2 == 0 ? "row1" : "row2"
> > puts "<tr class=#{row_class}><td>#{person.name}</td>
> > puts "Last person: #{person}" if i == people.length - 1
> > end
> >
> > I suppose you could extend Fixnum within a loop to include extra
> > methods
> > so that you could do something like this:
>
> people.each_with_index do |person, i|
> puts "First person: #{person} if person == people.first
> row_class = i.even? ? "row1" : "row2"
> puts "Last person: #{person} if person == people.last
> end
>
> How about that?
>
> --
> Eric Hodel - drbrain@segment7.net - http://se...
> FEC2 57F1 D465 EB15 5D6E 7C11 332A 551C 796C 9F04
>
>

And you could of course do something like (hey is this a valid use for
@@vars or is there a better way? -- does Ruby have the C concept of a
local static variable?)

class Object
@@nasty_bad_pseudo_global_hash = Hash.new(true)
def alternate(*args)
doit = @@nasty_bad_pseudo_global_hash[caller.first]
@@nasty_bad_pseudo_global_hash[caller.first] = !doit
yield(args) if doit
end
end

(1..10).each do |i|
alternate(i) { |x| puts x }
end


ES

3/30/2005 11:28:00 PM

0


In data 3/30/2005, "Berger, Daniel" <Daniel.Berger@qwest.com> ha
scritto:

>> -----Original Message-----
>> From: pmak@aaanime.net [mailto:pmak@aaanime.net]
>> Sent: Wednesday, March 30, 2005 11:30 AM
>> To: ruby-talk ML
>> Subject: Syntax sugar idea for loops
>>
>>
>> I was working with a proprietary programming language called
>> Traction <www.tractionsoftware.com>, and I noticed something
>> pretty cool they had in their loop constructs.
>>
>> Consider the following Ruby code:
>>
>> every_other = true
>> people.each do |person|
>> every_other = !every_other
>> row_class = every_other ? 'row1' : 'row2'
>> puts "<tr class=#{row_class}><td>#{person.name}</td>
>> <td>#{person.email}</td></tr>"
>> end
>>
>> This code prints out an HTML table of peoples' names and
>> e-mail addresses. The <tr> tags alternate with having
>> class="row1" and class="row2", allowing every other row to be
>> colored differently.
>>
>> Consider these two lines of the code, though:
>>
>> every_other = true
>> every_other = !every_other
>>
>> These lines could be replaced by syntax sugar. Traction has
>> the following "Special Loop Tags":
>>
>> <loop.first>: true if this is the first iteration of the loop
>> <loop.inner> true if this is not the first or last
>> iteration of the loop
>> <loop.odd> true if this is an odd iteration
>> <loop.last>: true if this is the last iteration of the loop
>>
>> (In the case of nested loops, they apply to the innermost
>> loop.) Maybe Ruby could use this sort of syntax sugar, too?
>> So in my example above, there would be a built-in variable
>> that replaces my "every_other" variable.
>
>I think Enumerable#each_with_index largely eliminates the need for such
>syntactic sugar. Consider:
>
>people.each_with_index do |person, i|
> puts "First person: #{person}" if i == 0
> row_class = i%2 == 0 ? "row1" : "row2"
> puts "<tr class=#{row_class}><td>#{person.name}</td>
> puts "Last person: #{person}" if i == people.length - 1
>end
>
>I suppose you could extend Fixnum within a loop to include extra methods
>so that you could do something like this:
>
>people.each_with_index do |person, i|
> puts "First person: #{person} if i.first?
> row_class = i.even? ? "row1" : "row2"
> puts "Last person: #{person} if i.last?
>end
>
>But that would mean making some serious modifications to Enumerable
>(wouldn't it?). Not a bad idea, just not worth the added code
>maintenance IMHO.

Adding Enumerable#step (or maybe Array#step) might not
be a bad idea but I do not know how common that usage
might be.

>Regards,
>
>Dan

E



Robert Klemme

3/31/2005 7:32:00 AM

0


"Berger, Daniel" <Daniel.Berger@qwest.com> schrieb im Newsbeitrag
news:8FE83020B9E1A248A182A9B0A7B76E7358B379@itomae2km07.AD.QINTRA.COM...
> > -----Original Message-----
> > From: pmak@aaanime.net [mailto:pmak@aaanime.net]
> > Sent: Wednesday, March 30, 2005 11:30 AM
> > To: ruby-talk ML
> > Subject: Syntax sugar idea for loops
> >
> >
> > I was working with a proprietary programming language called
> > Traction <www.tractionsoftware.com>, and I noticed something
> > pretty cool they had in their loop constructs.
> >
> > Consider the following Ruby code:
> >
> > every_other = true
> > people.each do |person|
> > every_other = !every_other
> > row_class = every_other ? 'row1' : 'row2'
> > puts "<tr class=#{row_class}><td>#{person.name}</td>
> > <td>#{person.email}</td></tr>"
> > end
> >
> > This code prints out an HTML table of peoples' names and
> > e-mail addresses. The <tr> tags alternate with having
> > class="row1" and class="row2", allowing every other row to be
> > colored differently.
> >
> > Consider these two lines of the code, though:
> >
> > every_other = true
> > every_other = !every_other
> >
> > These lines could be replaced by syntax sugar. Traction has
> > the following "Special Loop Tags":
> >
> > <loop.first>: true if this is the first iteration of the loop
> > <loop.inner> true if this is not the first or last
> > iteration of the loop
> > <loop.odd> true if this is an odd iteration
> > <loop.last>: true if this is the last iteration of the loop
> >
> > (In the case of nested loops, they apply to the innermost
> > loop.) Maybe Ruby could use this sort of syntax sugar, too?
> > So in my example above, there would be a built-in variable
> > that replaces my "every_other" variable.
>
> I think Enumerable#each_with_index largely eliminates the need for such
> syntactic sugar. Consider:
>
> people.each_with_index do |person, i|
> puts "First person: #{person}" if i == 0
> row_class = i%2 == 0 ? "row1" : "row2"
> puts "<tr class=#{row_class}><td>#{person.name}</td>
> puts "Last person: #{person}" if i == people.length - 1
> end

Yeah, "odd" and "even" are much too specific IMHO. Using the index is the
most general solution. That way you can do things like shown above plus:

people.each_with_index do |person, i|
row_class = "row#{(i%2)+1}"
puts "<tr class=#{row_class}><td>#{person.name}</td>
end

people.each_with_index do |person, i|
row_class = case i % 3
when 0; "rowx"
when 1; "rowy"
when 2; "rowz"
end
puts "<tr class=#{row_class}><td>#{person.name}</td>
end

ROW_CLASS = ["foo", "bar", "baz"]
....
people.each_with_index do |person, i|
puts "<tr class=#{ROW_CLASS[i %
ROW_CLASS.size]}><td>#{person.name}</td>
end

The last one being the most efficient one I guess.

Kind regards

robert

Lasse Koskela

3/31/2005 7:54:00 AM

0

On Thu, 31 Mar 2005 16:34:44 +0900, Robert Klemme <bob.news@gmx.net> wrote:
> Yeah, "odd" and "even" are much too specific IMHO. Using the index is the
> most general solution.

True, odd and even are rather specific but is that such a bad thing,
really? If the odd-even semantics are a common need, why not add
support for it in the language? I mean, why else would Ruby have
Array.each etc. instead of for (i=0; i < x; i++) which is clearly more
powerful in terms of all the things you can do with it?


-Lasse-


Luke Graham

3/31/2005 8:43:00 AM

0

On Thu, 31 Mar 2005 16:54:25 +0900, Lasse Koskela
<lasse.koskela@gmail.com> wrote:
> On Thu, 31 Mar 2005 16:34:44 +0900, Robert Klemme <bob.news@gmx.net> wrote:
> > Yeah, "odd" and "even" are much too specific IMHO. Using the index is the
> > most general solution.
>
> True, odd and even are rather specific but is that such a bad thing,
> really? If the odd-even semantics are a common need, why not add
> support for it in the language? I mean, why else would Ruby have
> Array.each etc. instead of for (i=0; i < x; i++) which is clearly more
> powerful in terms of all the things you can do with it?

Internal and external iterators are equivalent given the existance
of continuations. It may be interesting to explore the possibilities
of representing flow control as an object. To start the debate...

for () {
case for.special # Cant think of a better name right now :(
when for.first
..
when for.last
..
for.restart if error
else
...
for.next
puts "We get here, unlike the real next keyword"
end
}

Please note, I am -not- suggesting these for Ruby. I dont even like the
odd/even idea personally. Im brainstorming to see what is possible and
would like to see what others can come up with as well.

--
spooq


Robert Klemme

3/31/2005 8:59:00 AM

0


"Lasse Koskela" <lasse.koskela@gmail.com> schrieb im Newsbeitrag
news:3975e2d105033023544bb28311@mail.gmail.com...
> On Thu, 31 Mar 2005 16:34:44 +0900, Robert Klemme <bob.news@gmx.net>
wrote:
> > Yeah, "odd" and "even" are much too specific IMHO. Using the index is
the
> > most general solution.
>
> True, odd and even are rather specific but is that such a bad thing,
> really? If the odd-even semantics are a common need, why not add
> support for it in the language?

Then I'd still prefer

class Fixnum
def odd?() self % 2 == 1 end
def even?() self % 2 == 0 end
end

over an iteration specific thing.

> I mean, why else would Ruby have
> Array.each etc. instead of for (i=0; i < x; i++) which is clearly more
> powerful in terms of all the things you can do with it?

Yeah, true. But it's always balancing convenience vs. bloat: if you stick
too much convenience functionality into a language / library then it'll be
too bloated and there will be too many ways to do a single thing. I think
that odd and even for iterations is not general enough and this not used
too much. I may be wrong here though.

Kind regards

robert

Jon Raphaelson

3/31/2005 9:09:00 AM

0

Luke Graham wrote:
> On Thu, 31 Mar 2005 16:54:25 +0900, Lasse Koskela
> <lasse.koskela@gmail.com> wrote:
>
>>On Thu, 31 Mar 2005 16:34:44 +0900, Robert Klemme <bob.news@gmx.net> wrote:
>>
>>>Yeah, "odd" and "even" are much too specific IMHO. Using the index is the
>>>most general solution.
>>
>>True, odd and even are rather specific but is that such a bad thing,
>>really? If the odd-even semantics are a common need, why not add
>>support for it in the language? I mean, why else would Ruby have
>>Array.each etc. instead of for (i=0; i < x; i++) which is clearly more
>>powerful in terms of all the things you can do with it?
>
>
> Internal and external iterators are equivalent given the existance
> of continuations. It may be interesting to explore the possibilities
> of representing flow control as an object. To start the debate...
>
> for () {
> case for.special # Cant think of a better name right now :(
> when for.first
> ..
> when for.last
> ..
> for.restart if error
> else
> ...
> for.next
> puts "We get here, unlike the real next keyword"
> end
> }
>
> Please note, I am -not- suggesting these for Ruby. I dont even like the
> odd/even idea personally. Im brainstorming to see what is possible and
> would like to see what others can come up with as well.
>

This seems to me like something of what generators are in python, which
is just a function that yields instead of returns. I'm not an expert,
but they are really powerful and useful for defining custom iterators
and the like.

This generator is basically an open ended list of integers that vary by
2 ( I would like to say that I use ruby and not python, and I'm not
really fluent in python. So if this is wrong, will someone correct me
please? )

<snip python code>

def every_other(num):
while 1:
num += 2
yield num


odds = every_other(3)

odds.next() #=> 5
odds.next() #=> 7
odds.next() #=> 9
odds.next() #=> 11
odds.next() #=> 13
odds.next() #=> 15

... and so on.

I really like the idea of generators, and think that something like them
explicity might bee useful in ruby. I know it would be not-quite-trivial
to write a generator class (and there might be one already,) but they
are a nifty language feature that python has going for it.



Relm

3/31/2005 9:57:00 AM

0

Robert Klemme

3/31/2005 11:00:00 AM

0


"Jon Raphaelson" <jonraphaelson@gmail.com> schrieb im Newsbeitrag
news:424BBE2E.5000406@gmail.com...
> Luke Graham wrote:
> > On Thu, 31 Mar 2005 16:54:25 +0900, Lasse Koskela
> > <lasse.koskela@gmail.com> wrote:
> >
> >>On Thu, 31 Mar 2005 16:34:44 +0900, Robert Klemme <bob.news@gmx.net>
wrote:
> >>
> >>>Yeah, "odd" and "even" are much too specific IMHO. Using the index
is the
> >>>most general solution.
> >>
> >>True, odd and even are rather specific but is that such a bad thing,
> >>really? If the odd-even semantics are a common need, why not add
> >>support for it in the language? I mean, why else would Ruby have
> >>Array.each etc. instead of for (i=0; i < x; i++) which is clearly more
> >>powerful in terms of all the things you can do with it?
> >
> >
> > Internal and external iterators are equivalent given the existance
> > of continuations. It may be interesting to explore the possibilities
> > of representing flow control as an object. To start the debate...
> >
> > for () {
> > case for.special # Cant think of a better name right now :(
> > when for.first
> > ..
> > when for.last
> > ..
> > for.restart if error
> > else
> > ...
> > for.next
> > puts "We get here, unlike the real next keyword"
> > end
> > }
> >
> > Please note, I am -not- suggesting these for Ruby. I dont even like
the
> > odd/even idea personally. Im brainstorming to see what is possible and
> > would like to see what others can come up with as well.
> >
>
> This seems to me like something of what generators are in python, which
> is just a function that yields instead of returns. I'm not an expert,
> but they are really powerful and useful for defining custom iterators
> and the like.
>
> This generator is basically an open ended list of integers that vary by
> 2 ( I would like to say that I use ruby and not python, and I'm not
> really fluent in python. So if this is wrong, will someone correct me
> please? )
>
> <snip python code>
>
> def every_other(num):
> while 1:
> num += 2
> yield num
>
>
> odds = every_other(3)
>
> odds.next() #=> 5
> odds.next() #=> 7
> odds.next() #=> 9
> odds.next() #=> 11
> odds.next() #=> 13
> odds.next() #=> 15
>
> .. and so on.
>
> I really like the idea of generators, and think that something like them
> explicity might bee useful in ruby. I know it would be not-quite-trivial
> to write a generator class (and there might be one already,) but they
> are a nifty language feature that python has going for it.

It's been done already for arbitrary Enumerations:
http://www.ruby-doc.org/core/classes/Gene...

It's trivial for odd or even numbers.

robert