# How to add an iterator to a class?

**URL:** <https://www.ruby-forum.com/t/how-to-add-an-iterator-to-a-class/115333>\
**Category:** Ruby\
**Created:** [September 24, 2007, 4:42am UTC](https://www.ruby-forum.com/t/how-to-add-an-iterator-to-a-class/115333 "2007-09-24T04:42:34Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![mschwab](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/59ef9b/32.png) [@mschwab](https://www.ruby-forum.com/u/mschwab)\
**Post date:** [September 24, 2007, 4:42am UTC](https://www.ruby-forum.com/t/how-to-add-an-iterator-to-a-class/115333/1 "2007-09-24T04:42:34Z")

</div>

I have a simple class (this is just an example, so ignore any syntax or  
style errors):

class MyArray  
def initialize  
@a = Array.new  
end  
def Push( item )  
@a.push( item )  
end  
def GetArray  
return @a  
end  
end

And I have this code:

myarray = MyArray.new  
myarray.Push( 1 )  
myarray.Push( 2 )

myarray.GetArray.each do | i |  
puts i  
end

So my question is: How do I replace GetArray with something more  
elegant,  
that gives MyArray a method named .each that I can call directly?

Michael Steiner

---

<div class="post-metadata">

**Author:** ![mschwab](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/59ef9b/32.png) [@mschwab](https://www.ruby-forum.com/u/mschwab)\
**Post date:** [September 24, 2007, 5:42am UTC](https://www.ruby-forum.com/t/how-to-add-an-iterator-to-a-class/115333/2 "2007-09-24T05:42:25Z")

</div>

Mike S. wrote:

> I have a simple class (this is just an example, so ignore any syntax or  
> style errors):
> 
> class MyArray  
> def initialize  
> @a = Array.new  
> end  
> def Push( item )  
> @a.push( item )  
> end  
> def GetArray  
> return @a  
> end  
> end
> 
> And I have this code:
> 
> myarray = MyArray.new  
> myarray.Push( 1 )  
> myarray.Push( 2 )
> 
> myarray.GetArray.each do | i |  
> puts i  
> end
> 
> So my question is: How do I replace GetArray with something more  
> elegant,  
> that gives MyArray a method named .each that I can call directly?
> 
> Michael Steiner

Hi Michael,

What you want to do is mixin the Enumerable module into your class:

[http://www.ruby-doc.org/core/classes/Enumerable.html](http://www.ruby-doc.org/core/classes/Enumerable.html)

You then have to define an #each method that yields for each member of  
your collection.

For example:

class MyArray  
include Enumerable

def initialize  
@a = Array.new  
end

def each  
for e in @a do  
yield e  
end  
end  
end

From there, your class will have all of the methods defined in  
Enumerable.

David B. Williams  
[http://www.cybersprocket.com](http://www.cybersprocket.com)

---

<div class="post-metadata">

**Author:** ![mschwab](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/59ef9b/32.png) [@mschwab](https://www.ruby-forum.com/u/mschwab)\
**Post date:** [September 24, 2007, 6:22am UTC](https://www.ruby-forum.com/t/how-to-add-an-iterator-to-a-class/115333/3 "2007-09-24T06:22:43Z")

</div>

Mike S. wrote:

> So my question is: How do I replace GetArray with something more  
> elegant,  
> that gives MyArray a method named .each that I can call directly?

each() is an “iterator”. An iterator is a method that uses a “yield  
statement”. A yield statement acts similar to a method call, and looks  
like this:

yield some\_val

yield calls the block and sends it the argument specified to the right  
of ‘yield’. The method that contains the yield statement, i.e. each(),  
halts and waits for the block to finish executing, and then execution  
continues in the method. That interaction is very similar to a method  
that calls another method:

def greet  
sleep(2)  
puts “hello”  
sleep(5)  
end

def start  
greet

```
x = 10
puts x

```

end

start

If you run that code, you’ll see that the method start() waits for  
greet() to finish executing before it outputs 10. yield works  
similarly: execution does not continue in the method that contains the  
yield statement, e.g. each(), until the block that the yield statement  
called finishes executing.

So, you need to define a method called each, and inside each you are  
going to use a yield statement that sends values to a block. What  
values? The values are the elements of your array. Since you are  
generally going to need to yield more than one value, i.e. your array  
will have more than one element in it, you can put your yield statement  
inside a loop:

class MyArray  
def initialize  
@a = Array.new  
end  
def push( item )  
@a.push( item )  
end

```
def each
    count = 0
    while elmt = @a[count]
        yield elmt
        count += 1
    end
end

```

end

arr = MyArray.new  
arr.push(1)  
arr.push(2)  
arr.push(3)

arr.each{|elmt| puts elmt +2}

---

<div class="post-metadata">

**Author:** ![mschwab](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/59ef9b/32.png) [@mschwab](https://www.ruby-forum.com/u/mschwab)\
**Post date:** [September 24, 2007, 6:52am UTC](https://www.ruby-forum.com/t/how-to-add-an-iterator-to-a-class/115333/4 "2007-09-24T06:52:24Z")

</div>

Here’s a super simple example of an iterator:

def test  
yield  
yield  
yield

```
puts "all done in test"

```

end

test {puts “hello”; sleep(2)}

In that example, test() calls the block but does not send it any  
arguments–just like you can call a method and not send it any  
arguments. Note that the block is not defined to accept any arguments.

When the first yield statement is encountered, the block is called. How  
does the yield statement know what block to call? yield calls the block  
specified to the right of the test method call. What if you call test  
and don’t specify a block?

r4test.rb:2:in `test’: no block given (LocalJumpError)  
from r4test.rb:9

After the first yield statement in test is encountered, execution halts  
at the point of the first yield statement until the block outputs  
“hello” and finishes sleeping. Then execution continues in test. The  
next line in test is another yield statement, so the block is called  
again, and execution halts in test until the block finishes. The same  
thing happens a third time. Finally, test outputs its terminating  
message.

Blocks can also return values to a yield statement–just like a method  
can return a value to a method call, e.g.

def get\_calc  
10 \* 2  
end

def do\_homework  
answer = get\_calc #return value replaces the method call in the  
code  
puts answer  
end

do\_homework

Here is how a block returns a value to a yield statement:

def test  
result = yield 10 #catch the value returned by the block in a  
variable

```
puts result

```

end

test {10 \* 2}

---

<div class="post-metadata">

**Author:** ![mschwab](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/59ef9b/32.png) [@mschwab](https://www.ruby-forum.com/u/mschwab)\
**Post date:** [September 25, 2007, 11:03pm UTC](https://www.ruby-forum.com/t/how-to-add-an-iterator-to-a-class/115333/5 "2007-09-25T23:03:54Z")

</div>

> class MyArray
> 
> So my question is: How do I replace GetArray with something  
> more elegant,  
> that gives MyArray a method named .each that I can call directly?
> 
> Michael Steiner

class MyArray  
def each  
@a.each do |x|  
yield x  
end  
end  
end

Though you may be better off simply extending Array and just add custom  
functionality - Array is pretty good at implementing push and each.

You may also want to check out the Enumerable mixin if you’re going to  
play  
with collections of objects and don’t want to inherit.

HTH,

Felix

---

<div class="post-metadata">

**Author:** ![mschwab](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/59ef9b/32.png) [@mschwab](https://www.ruby-forum.com/u/mschwab)\
**Post date:** [September 24, 2007, 6:59am UTC](https://www.ruby-forum.com/t/how-to-add-an-iterator-to-a-class/115333/6 "2007-09-24T06:59:08Z")

</div>

7stud – wrote:

> Here is how a block returns a value to a yield statement:
> 
> def test  
> result = yield 10 #catch the value returned by the block in a  
> variable
> 
> ```
> puts result
> 
> ```
> 
> end
> 
> test {10 \* 2}

Whoops. That should be:

def test  
result = yield 10

```
puts result

```

end

test {|num| num \* 2} #block is defined to accept an arg

---

<div class="post-metadata">

**Author:** ![mschwab](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/59ef9b/32.png) [@mschwab](https://www.ruby-forum.com/u/mschwab)\
**Post date:** [September 25, 2007, 11:10pm UTC](https://www.ruby-forum.com/t/how-to-add-an-iterator-to-a-class/115333/7 "2007-09-25T23:10:15Z")

</div>

class MyArray  
def initialize  
@a = [“hey”, “whats”, “up!”]  
end

```
def each(&block)
    @a.each &block
end

```

end  
m = MyArray.new  
m.each{|el| p el} # =\> “hey”  
“whats”  
“up!”

here we are simply reimplementing the each function of the array class,  
if  
the need is to implement it functionally,  
then we should use the “yield” explicitly.

---

<div class="post-metadata">

**Author:** ![mschwab](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/59ef9b/32.png) [@mschwab](https://www.ruby-forum.com/u/mschwab)\
**Post date:** [October 3, 2007, 11:55am UTC](https://www.ruby-forum.com/t/how-to-add-an-iterator-to-a-class/115333/8 "2007-10-03T11:55:23Z")

</div>

On 24.09.2007 05:42, David B. Williams wrote:

> > ```
> > end
> > 
> > ```
> 
> Hi Michael,  
> class MyArray  
> end  
> end

In this simple case (i.e. without filtering or converting) you can even  
do this:

def each(&b)  
@a.each(&b)  
self  
end

Also note that conventionally #each returns self.

Kind regards

robert
