Thursday, April 15, 2004

One of the things that’s rather high on my mind’s sort order these days is Ruby programming. I have been thinking about what makes ruby so neat a language to use, simply by virtue of what the language lets me do.

 

One of the early things that got me hooked to Ruby, was its support for iterators. If you have been spoiled by many years of C programming, like me, then its time to wake up and take a look at a few things that C can’t pull off, at least not very easily.

 

What is an iterator?

Let’s take a look at code like this, where there is a piece of code that produces value and a piece of code that consumes values.

 

void produce()
{

for (int i=0;i<100;i++)
            if( i%5 == 0)
                  consumer(i);

}

 

void consumer(int v)
{

printf(“%d”,v);
}

 

All things considered this code is fine, except that the producer invokes the consumer. And simply because of that the consumer cannot maintain state. The only way the consumer can maintain state, ie remember something between two calls is to save variables into either static variables, or globals or into some object.

 

The would be the argument if the consumer function tried invoking the producer, where the producer will have to have a very contrived piece of code to remember variable values between calls.

 

From a perspective, an iterator solves exactly this problem. This is a ruby code:

 

def producer

      for i in 0..99

            if (i%5 == 0)

                  yield i

            end  

      end

end

 

def consumer

      producer() do |v|

            print v

      end

end

 

The ‘def’ keyword starts a function/method declaration. The code above for the producer should be rather easy to understand, except for the yield statement.

 

What does the yield do? The yield causes the function producer() to exit with the return value of the function as the parameter of the yield, in this case ‘i’.

 

The difference between yielding a value and actually doing a return is that the function can continue execution from the point of the yield statement.

 

The consumer function then simply invokes the producer() function and catches each of the yielded values. That is why these is a ‘do’ statement and a corresponding ‘end’ statement in the consumer code. The parameter for the do-end block is the ‘v’ that is enclosed in ||. Every time the producer yields a value, the value is available in ‘v’ and the do-end block is executed. When the block finishes the producer continues after the point of the yield.

 

So if you want to, say calculate the sum of all the values that the producer yields, then you can

 

def consumer

      sum = 0

      producer() do |v|

            sum = sum + v

      end

      print sum

end

 

 

Now that you have been introduced to the idea of iterators, I suggest you do some thinking about, especially if you have done a fair bit of C programming. Imagine how these functions would have to maintain state, what their call stacks will look like and such.

 

Now let me clean up on a few things. In ruby all functions are called methods, formally. So let’s start calling them methods. Secondly a lot of the Ruby libraries are built to support iterators so you will see the idea being used a lot. Thirdly, the do-end block can also be written as { } curly braces.

 

The methods that I have written have been written in a drawn out C-like style, so that the ideas are clear despite the slight difference in syntax. So lets just rewrite the two methods slightly more ruby-ishly and close this blog entry.

 

def producer

      100.times{|i| yield i if i%5 == 0}

end

 

def consumer

      sum = 0

      producer {|v| sum = sum + v}

      print sum

end

 

You can get Ruby from here, for your windows box:

http://rubyinstaller.sourceforge.net

Apr 13 2004 Tuesday 11-05AM

Monday, June 09, 2008 6:19:34 PM (Eastern Standard Time, UTC-05:00)
i think there is a bug in
def producer

100.times{|i| yield i if i%5 == 0}

end



def consumer

sum = 0

producer {|v| sum = sum + v}

print sum

end
Wednesday, July 16, 2008 6:05:00 PM (Eastern Standard Time, UTC-05:00)
The methods that I have written have been written in a drawn out C-like style, so that the ideas are clear despite the slight difference in syntax. So lets just rewrite the two methods slightly more ruby-ishly and close this blog entry.
sbs
Thursday, July 17, 2008 3:43:40 PM (Eastern Standard Time, UTC-05:00)
ı think that is very insteresting. slayt
Name
E-mail
Home page

Comment (Some html is allowed: a@href@title, strike) where the @ means "attribute." For example, you can use <a href="" title=""> or <blockquote cite="Scott">.  

Enter the code shown (prevents robots):

Live Comment Preview