The power of ruby

Hi,
As i get better writing ruby scripts (im pretty new), I often wonder
if im not exploiting the power of the language or that i’m casting
precedural language ideas onto my ruby scripts. I have here a little C
program that would like some of you to Rubi-tize if possible, so that
i can see how some of you that really know the language use it.

[code]============================================

#include <stdio.h>
#include <stdlib.h>
int I;
/-----------------------------/
void dodot(int x){
while(x>0){
printf(" “);
x–;
}
printf(”\n");
sleep(10);
}
/
-----------------------------*/
int main(int argc, char *argv[])
{
while(1){
while(I<75){
dodot(I);
I++;
}
while(I>0){
dodot(I);
I–;
}
}
return 0;
}
[/code]=============================================

Here is my unimaginitive attempt.

============================================== WIDTH=78; def do_dot(i) i.times{print " "} puts "*"; end loop{ 0.upto(WIDTH-1){|i| do_dot(i); } WIDTH.downto(1){|i| do_dot(i); } } =============================================

Thanks.

Yours is rather succinct, but I find that you can often capitalize
on return values of methods to shorten. Shorten, right? You’re
looking for shorter?

Here’s one:

WIDTH = 78
def do_dot( i )
puts( ( " " * i ) + “*” )
end
loop {
WIDTH.times { |i| do_dot(i) }.downto(0) { |i| do_dot(i) }
}

Check ya later.

_why

···

AW (sturmpanzer@metacrawler.com) wrote:

Here is my unimaginitive attempt.

============================================== WIDTH=78; def do_dot(i) i.times{print " "} puts "*"; end loop{ 0.upto(WIDTH-1){|i| do_dot(i); } WIDTH.downto(1){|i| do_dot(i); } } =============================================

My “imaginative” attempt is below.

Hi,
As i get better writing ruby scripts (im pretty new), I often wonder if
im not exploiting the power of the language or that i’m casting
precedural language ideas onto my ruby scripts. I have here a little C
program that would like some of you to Rubi-tize if possible, so that i
can see how some of you that really know the language use it.

[snip C code]

Here is my unimaginitive attempt.

============================================== WIDTH=78; def do_dot(i) i.times{print " "} puts "*"; end loop{ 0.upto(WIDTH-1){|i| do_dot(i); } WIDTH.downto(1){|i| do_dot(i); } } =============================================

Thanks.

=begin
starfield.rb, by Gavin Sinclair

This is a verbose, almost obfuscated implementation of a simple
program in Ruby. It is intended to demonstrate the following just
for the sake of it:
- class
- attr_reader
- Comparable mixin
- Range, esp. of user-defined type
- for x in y syntax
- array manipulation
=end

WIDTH = 78

class Star
include Comparable # Import comparison operations <, ==, …

attr_reader :n # Attribute ‘:n’ can be read through auto-defined
# method ‘n’.

def initialize(n) # Called when a new Star object is created.
@n = n
end

def <=>(other) # Compare to another Star.
@n <=> other.n
end

def succ # Next element in sequence, needed for Range.
Star.new(@n+1)
end

def to_s # The value that is returned when the object is
" " * @n + “*” # coerced into a String.
end
end

We can create a Range of Stars.

starfield = Star.new(0) … Star.new(WIDTH)

loop do

Print them in turn.

for star in starfield
puts star
end

To print them going back, we have to get dirty. Note that we

ignore the rightmost star, to get the effect you want.

for star in starfield.to_a.reverse[1…-1]
puts star
end
end

(END OF CODE)

Cheers,
Gavin

I thought it might be interesting to write an iterator:

WIDTH=78

def do_dot(i)
puts “#{’ ’ * i}*”
sleep 0.01
end

def up_and_down(low, high)
low.upto(high-1) do |i|
yield i
end
high.downto(low+1) do |i|
yield i
end
end

loop do
up_and_down(0, WIDTH) do |i|
do_dot(i)
end
end

The idea here is to separate what happens on each iteration from the
iterating itself, and perhaps to be able to re-use the iterator
somewhere else.

I also added a sleep, because otherwise the stars jump around a bit too
much in my terminal (Eterm).

Paul

···

On Wed, Aug 21, 2002 at 05:30:53AM +0900, AW wrote:

As i get better writing ruby scripts (im pretty new), I often wonder
if im not exploiting the power of the language or that i’m casting
precedural language ideas onto my ruby scripts. I have here a little C
program that would like some of you to Rubi-tize if possible, so that
i can see how some of you that really know the language use it.

AW wrote:

Hi,
As i get better writing ruby scripts (im pretty new), I often wonder
if im not exploiting the power of the language or that i’m casting
precedural language ideas onto my ruby scripts. I have here a little C
program that would like some of you to Rubi-tize if possible, so that
i can see how some of you that really know the language use it.

I’m very new, only started looking at Ruby Saturday / Sunday time. I
like it though :slight_smile:

Without looking at anyones attempts other than the C code, this is my
stab at it.

/-- code --/

example to print stars to screen

def printStar(location)
(1…location).each { |x| print " " }
print “*\n”
end

screenWidth = 78;

if ARGV.size == 1
# use argument unless its not a int (to_i returns 0 if item not an integer)
screenWidth = ARGV[0].to_i unless ARGV[0].to_i == 0
end

forward

1.upto(screenWidth) {|n| printStar(n)}

back

screenWidth.downto(1) {|n| printStar(n)}

Wow, Doing it that way had never accured to me.
How does that work that you can use dot notation from a bracket ‘}’ ?
I keep looking at the last line and I cant seem to grasp its
relationship, I mean, If the first set of ‘{}’ are containing the loop
from the ‘.times’ method, how do the second set relate?
Now i’m really confused. Thank you! :wink:

Yours is rather succinct, but I find that you can often capitalize
on return values of methods to shorten. Shorten, right? You’re
looking for shorter?

Im looking for exactly what you gave. different ways to express the
same output in Ruby. Shorter, longer, obsfucated, clear.
I just hope others will chime in and give some examples of their own
style.

···

Here’s one:

WIDTH = 78
def do_dot( i )
puts( ( " " * i ) + “*” )
end
loop {
WIDTH.times { |i| do_dot(i) }.downto(0) { |i| do_dot(i) }
}

Check ya later.

_why

AW (sturmpanzer@metacrawler.com) wrote:

Here is my unimaginitive attempt.

============================================== WIDTH=78; def do_dot(i) i.times{print " "} puts "*"; end loop{ 0.upto(WIDTH-1){|i| do_dot(i); } WIDTH.downto(1){|i| do_dot(i); } } =============================================

puts “#{’ ’ * i}*” ← That’s a very nice way of doing it.
I think sometimes i forget the “Everything is an object” concept. :wink:

···

I thought it might be interesting to write an iterator:

WIDTH=78

def do_dot(i)
puts “#{’ ’ * i}*”
sleep 0.01
end

def up_and_down(low, high)
low.upto(high-1) do |i|
yield i
end
high.downto(low+1) do |i|
yield i
end
end

loop do
up_and_down(0, WIDTH) do |i|
do_dot(i)
end
end

The idea here is to separate what happens on each iteration from the
iterating itself, and perhaps to be able to re-use the iterator
somewhere else.

I also added a sleep, because otherwise the stars jump around a bit too
much in my terminal (Eterm).

Paul

Great example!
Thats a lot to chew on.

···

My “imaginative” attempt is below.

=begin
starfield.rb, by Gavin Sinclair

This is a verbose, almost obfuscated implementation of a simple
program in Ruby. It is intended to demonstrate the following just
for the sake of it:

  • class
  • attr_reader
  • Comparable mixin
  • Range, esp. of user-defined type
  • for x in y syntax
  • array manipulation
    =end

WIDTH = 78

class Star
include Comparable # Import comparison operations <, ==, …

attr_reader :n # Attribute ‘:n’ can be read through auto-defined
# method ‘n’.

def initialize(n) # Called when a new Star object is created.
@n = n
end

def <=>(other) # Compare to another Star.
@n <=> other.n
end

def succ # Next element in sequence, needed for Range.
Star.new(@n+1)
end

def to_s # The value that is returned when the object is
" " * @n + “*” # coerced into a String.
end
end

We can create a Range of Stars.

starfield = Star.new(0) … Star.new(WIDTH)

loop do

Print them in turn.

for star in starfield
puts star
end

To print them going back, we have to get dirty. Note that we

ignore the rightmost star, to get the effect you want.

for star in starfield.to_a.reverse[1…-1]
puts star
end
end

(END OF CODE)

Cheers,
Gavin

Wow, Doing it that way had never accured to me.
How does that work that you can use dot notation from a bracket ‘}’ ?
I keep looking at the last line and I cant seem to grasp its
relationship, I mean, If the first set of ‘{}’ are containing the loop
from the ‘.times’ method, how do the second set relate?
Now i’m really confused. Thank you! :wink:

The bracketed code is a Proc object and I’m just manipulating its
return value directly. I could do this:

n = 78.times { |i|
do_dot( i )
}
n.downto( 0 ) { |i|
do_dot( i )
}

See, the Integer#times method returns the original Integer. So does
Integer#downto. Try these in IRb:

5.times {}
==>5
5.downto( 0 ) {}
==>5

So I can manipulate the return value by calling methods from the block.
The above code can be rewritten:

78.times do |i|
do_dot( i )
end.
downto( 0 ) do |i|
do_dot( i )
end

I have thought there might be a way to loop up and down through a Range
or Integer in Ruby in a single call, but I could think of how to do it
without adding a method to Integer or Range and wasting more chars than
the above.

Im looking for exactly what you gave. different ways to express the
same output in Ruby. Shorter, longer, obsfucated, clear.
I just hope others will chime in and give some examples of their own
style.

Well, in that case, I’ll include one that overrides Fixnum for ya:

def do_dot( i )
puts “#{’ ’ * i}*”
end
class Fixnum
def up_and_down( &p )
times( &p ); downto( 0, &p )
end
end
while 78.up_and_down { |i| do_dot( i ) }; end

Good luck.

_why

···

AW (sturmpanzer@metacrawler.com) wrote:

I keep looking at the last line and I cant seem to grasp its
relationship, I mean, If the first set of ‘{}’ are containing the loop
from the ‘.times’ method, how do the second set relate?

The .times method returns an int, try this :

C:> ruby -e “puts 5.times{}”
5
C:>

The block in curly brace: { |i| do_dot(i) } is only a parameter to .times.
Imagine it thus:

WIDTH.times( block_in_curly_brace)

Since the return value of this function is an int you can cascade it to get

WIDTH.times( block_in_curly_brace).downto(0) { |i| do_dot(i) }

Now i’m really confused. Thank you! :wink:

Hope I have not confused you more :wink:

– Shanko

···

Yours is rather succinct, but I find that you can often capitalize
on return values of methods to shorten. Shorten, right? You’re
looking for shorter?

Im looking for exactly what you gave. different ways to express the
same output in Ruby. Shorter, longer, obsfucated, clear.
I just hope others will chime in and give some examples of their own
style.

Here’s one:

WIDTH = 78
def do_dot( i )
puts( ( " " * i ) + “*” )
end
loop {
WIDTH.times { |i| do_dot(i) }.downto(0) { |i| do_dot(i) }
}

Check ya later.

_why

AW (sturmpanzer@metacrawler.com) wrote:

Here is my unimaginitive attempt.

============================================== WIDTH=78; def do_dot(i) i.times{print " "} puts "*"; end loop{ 0.upto(WIDTH-1){|i| do_dot(i); } WIDTH.downto(1){|i| do_dot(i); } } =============================================

I understand you’re fairly new to Ruby, AW, but I must give you some guidance
here. As cool as <<puts “#{’ ’ * i}*”>> is, the main point of Paul’s program
was the iterator. The fact that his method “up_and_down” simply counts up and
down, and is completely independent of what is being done with that count.
That is good design, and highlights Ruby as a good language.

I think you should thank Paul for imparting that lesson :wink:

Cheers,
Gavin

···

----- Original Message -----
From: “AW” sturmpanzer@metacrawler.com
Newsgroups: comp.lang.ruby
To: “ruby-talk ML” ruby-talk@ruby-lang.org
Sent: Thursday, August 22, 2002 5:33 AM
Subject: Re: the power of ruby

puts “#{’ ’ * i}*” ← That’s a very nice way of doing it.
I think sometimes i forget the “Everything is an object” concept. :wink:

I thought it might be interesting to write an iterator:

WIDTH=78

def do_dot(i)
puts “#{’ ’ * i}*”
sleep 0.01
end

def up_and_down(low, high)
low.upto(high-1) do |i|
yield i
end
high.downto(low+1) do |i|
yield i
end
end

loop do
up_and_down(0, WIDTH) do |i|
do_dot(i)
end
end

The idea here is to separate what happens on each iteration from the
iterating itself, and perhaps to be able to re-use the iterator
somewhere else.

I also added a sleep, because otherwise the stars jump around a bit too
much in my terminal (Eterm).

Paul

Your version runs about 10X faster than mine. but i see why now.
I had far to many writes to IO.
The precedence is a bit confusing at first. I wasnt aware that the
times{} must complete for going to downto{}.
this is a wonderfull example. I think I may be a bit too timid about
truely exploiting Ruby’s power.

···

I keep looking at the last line and I cant seem to grasp its
relationship, I mean, If the first set of ‘{}’ are containing the loop
from the ‘.times’ method, how do the second set relate?

The .times method returns an int, try this :

C:> ruby -e “puts 5.times{}”
5
C:>

The block in curly brace: { |i| do_dot(i) } is only a parameter to .times.
Imagine it thus:

WIDTH.times( block_in_curly_brace)

Since the return value of this function is an int you can cascade it to get

WIDTH.times( block_in_curly_brace).downto(0) { |i| do_dot(i) }

Now i’m really confused. Thank you! :wink:

Hope I have not confused you more :wink:

– Shanko

Yours is rather succinct, but I find that you can often capitalize
on return values of methods to shorten. Shorten, right? You’re
looking for shorter?

Im looking for exactly what you gave. different ways to express the
same output in Ruby. Shorter, longer, obsfucated, clear.
I just hope others will chime in and give some examples of their own
style.

Here’s one:

WIDTH = 78
def do_dot( i )
puts( ( " " * i ) + “*” )
end
loop {
WIDTH.times { |i| do_dot(i) }.downto(0) { |i| do_dot(i) }
}

Check ya later.

_why

AW (sturmpanzer@metacrawler.com) wrote:

Here is my unimaginitive attempt.

============================================== WIDTH=78; def do_dot(i) i.times{print " "} puts "*"; end loop{ 0.upto(WIDTH-1){|i| do_dot(i); } WIDTH.downto(1){|i| do_dot(i); } } =============================================

I understand you’re fairly new to Ruby, AW, but I must give you some guidance
here. As cool as <<puts “#{’ ’ * i}*”>> is, the main point of Paul’s program
was the iterator. The fact that his method “up_and_down” simply counts up and
down, and is completely independent of what is being done with that count.
That is good design, and highlights Ruby as a good language.

I think you should thank Paul for imparting that lesson :wink:

Cheers,
Gavin

Of course!.
I want to thank everybody who responded.
Everybody’s code examples have given me a lot to think about.
Being able to see the way other people use ruby to express the same
result helps me learn to do things the ruby way and not write like im
using Pascal with a diff syntax. I dont want to get get stuck treating
ruby just another scriptig language with lots of handy polymophic
methods built in, Its more than that.

Aaron.