# Redefe each to include each\_with\_index and arity=2

**URL:** <https://www.ruby-forum.com/t/redefe-each-to-include-each-with-index-and-arity-2/148237>\
**Category:** Ruby\
**Created:** [September 10, 2008, 8:00pm UTC](https://www.ruby-forum.com/t/redefe-each-to-include-each-with-index-and-arity-2/148237 "2008-09-10T20:00:34Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![dandiebolt](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/a87d85/32.png) [@dandiebolt](https://www.ruby-forum.com/u/dandiebolt)\
**Post date:** [September 10, 2008, 8:00pm UTC](https://www.ruby-forum.com/t/redefe-each-to-include-each-with-index-and-arity-2/148237/1 "2008-09-10T20:00:34Z")

</div>

# Is is possible to redefine each so that each\_with\_index behavior can be acheived with an extra parameter to the block each is called with? In other words, how do you redefine each so that instead of using this construct: Â Â a.each\_with\_index do |item,index| Â Â end Â you can use this one: Â Â a.each do |item,index| Â Â end Â as well not disturbing this usage: Â Â a.each do |item| Â Â end Â

This is my attempt to redefine Array#each but it does not work:  
Â  
class Array  
Â alias :old\_each :each  
Â def each(&block)  
Â Â Â puts “arity=#{block.arity}”  
Â Â Â case block.arity  
Â Â Â when 1  
Â Â Â Â Â old\_each &block  
Â Â Â when 2  
Â Â Â Â Â each\_with\_index &block  
Â Â Â end  
Â end  
end  
Â  
a=[1,2,3]  
Â  
irb(main):030:0\> a.each do |item|  
irb(main):031:1_Â puts “item=#{item}”  
irb(main):032:1\> end  
arity=1  
item=1  
item=2  
item=3  
=\> [1, 2, 3]  
Â  
irb(main):033:0\> a.each do |item,index|  
irb(main):034:1_Â puts “item=#{item}, index=#{index}”  
irb(main):035:1\> end  
arity=2  
arity=-1  
=\> [1, 2, 3]

---

<div class="post-metadata">

**Author:** ![dandiebolt](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/a87d85/32.png) [@dandiebolt](https://www.ruby-forum.com/u/dandiebolt)\
**Post date:** [September 10, 2008, 8:52pm UTC](https://www.ruby-forum.com/t/redefe-each-to-include-each-with-index-and-arity-2/148237/2 "2008-09-10T20:52:18Z")

</div>

Dan D. wrote:

> Is is possible to redefine each so that each\_with\_index behavior can be  
> acheived with an extra parameter to the block each is called with? In  
> other words, how do you redefine each so that instead of using this  
> construct:

> ======  
> This is my attempt to redefine Array#each but it does not work:  
> Â  
> class Array  
> Â alias :old\_each :each  
> Â def each(&block)  
> Â Â Â puts “arity=#{block.arity}”  
> Â Â Â case block.arity  
> Â Â Â when 1  
> Â Â Â Â Â old\_each &block  
> Â Â Â when 2  
> Â Â Â Â Â each\_with\_index &block  
> Â Â Â end  
> Â end  
> end  
> Â  
> a=[1,2,3]  
> Â

I’m not exactly sure why your code does not work. It seems that  
each\_with\_index and each depend on each other in ways which you are not  
capturing with your redefined each. But you can roll your own index  
tracking:

def each(&block)  
i = 0  
arity = block.arity  
old\_each do |curr|  
case arity  
when 1: yield curr  
else yield curr, i  
end  
i+=1  
end  
end

---

<div class="post-metadata">

**Author:** ![dandiebolt](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/a87d85/32.png) [@dandiebolt](https://www.ruby-forum.com/u/dandiebolt)\
**Post date:** [September 10, 2008, 9:42pm UTC](https://www.ruby-forum.com/t/redefe-each-to-include-each-with-index-and-arity-2/148237/3 "2008-09-10T21:42:10Z")

</div>

> … each\_with\_index and each depend on each other  
> Â  
> Maybe someone with more knowlege can track this dependance down. I am  
> keen to learn, but I have to admit thatÂ I am stretching my understanding  
> of the Ruby language here.  
> Â  
> I would like to ask others if they think having each overloaded to take  
> either |item| or |item,index| would be a general language improvement.  
> Also, for greatest generality should this proposed redefinition of each  
> be made to the class Array or to the enumerator mixin or somewhere else?

---

<div class="post-metadata">

**Author:** ![dandiebolt](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/a87d85/32.png) [@dandiebolt](https://www.ruby-forum.com/u/dandiebolt)\
**Post date:** [September 10, 2008, 10:07pm UTC](https://www.ruby-forum.com/t/redefe-each-to-include-each-with-index-and-arity-2/148237/4 "2008-09-10T22:07:15Z")

</div>

> I would like to ask others if they think having each overloaded to take  
> either |item| or |item,index| would be a general language improvement.  
> Also, for greatest generality should this proposed redefinition of each  
> be made to the class Array or to the enumerator mixin or somewhere else?

Like you, I’ve wondered why each could not do both things. On the one  
hand it would be nice if it supported the index functionality. However,  
it is really a breaking change. Consider what a and b are assigned  
currently at each iteration of the following, and what they would be  
assigned under your proposal.

[[1,2], [3,4]].each {|a,b|}

To answer your second question, each() must know the details of the  
container, and so it cannot be in a mixin. The Enumerable mixin defines  
functionality in terms of ‘each’ which must be supplied by the class  
into which you mix it in.

---

<div class="post-metadata">

**Author:** ![dandiebolt](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/a87d85/32.png) [@dandiebolt](https://www.ruby-forum.com/u/dandiebolt)\
**Post date:** [September 12, 2008, 12:55pm UTC](https://www.ruby-forum.com/t/redefe-each-to-include-each-with-index-and-arity-2/148237/5 "2008-09-12T12:55:57Z")

</div>

> I’m not exactly sure why your code does not work. It seems that each\_with\_index and each depend on each other in ways which you are not capturing with your redefined each.

I am not sure why either but by aliasing each and each\_with\_index within  
Array and tracing execution with some puts statements I learned that  
each\_with\_index is implemented by calling each.

In any event, I used your code when arity=2 and the following now works

irb(main):028:0\> a=[1,2,3]  
=\> [1, 2, 3]  
irb(main):029:0\>  
irb(main):030:0\* a.each do |item|  
irb(main):031:1\*Â Â puts “item=#{item}”  
irb(main):032:1\> end  
item=1  
item=2  
item=3  
=\> [1, 2, 3]

irb(main):033:0\* a.each do |item,index|  
irb(main):034:1\*Â Â puts “item=#{item} index=#{index}”  
irb(main):035:1\> end  
item=1 index=0  
item=2 index=1  
item=3 index=2

I would like to learn how this same technique can be applied to hashes,  
enums, & ranges and all enumerables.

This is my re-definition of Array:

class Array  
Â alias :old\_each :each  
Â def each(&block)  
Â Â Â case block.arity  
Â Â Â when 1  
Â Â Â Â Â old\_each &block  
Â Â Â when 2  
Â Â Â Â Â i = 0  
Â Â Â Â Â old\_each do |curr|  
Â Â Â Â Â Â Â yield curr, i  
Â Â Â Â Â Â Â i+=1  
Â Â Â Â Â end  
Â Â Â end  
Â end  
end

---

<div class="post-metadata">

**Author:** ![dandiebolt](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/a87d85/32.png) [@dandiebolt](https://www.ruby-forum.com/u/dandiebolt)\
**Post date:** [September 11, 2008, 2:55am UTC](https://www.ruby-forum.com/t/redefe-each-to-include-each-with-index-and-arity-2/148237/6 "2008-09-11T02:55:53Z")

</div>

On Sep 10, 2:59 pm, “DanDiebolt.exe” [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> > … each\_with\_index and each depend on each other
> 
> Maybe someone with more knowlege can track this dependance down. I am keen to learn, but I have to admit that I am stretching my understanding of the Ruby language here.
> 
> I would like to ask others if they think having each overloaded to take either |item| or |item,index| would be a general language improvement. Also, for greatest generality should this proposed redefinition of each be made to the class Array or to the enumerator mixin or somewhere else?

Can’t do it, it would break things.

I’ve always though an special ‘it’ object would be nice though. Eg.

[:a, :b, c:].each do |e|  
it.index  
it.first?  
it.last?  
end

T.

---

<div class="post-metadata">

**Author:** ![dandiebolt](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/a87d85/32.png) [@dandiebolt](https://www.ruby-forum.com/u/dandiebolt)\
**Post date:** [September 12, 2008, 3:25pm UTC](https://www.ruby-forum.com/t/redefe-each-to-include-each-with-index-and-arity-2/148237/7 "2008-09-12T15:25:48Z")

</div>

On Wed, Sep 10, 2008 at 7:53 PM, DanDiebolt.exe [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)  
wrote:

> arity=2  
> arity=-1

Where do you think the arity=-1 does come from? Does this ring a bell?

Actually each\_with\_index will use a block with \*args calling each again.  
Now that brings us to why your idea might not be as good as you  
thaught at first sight:

[[:a, 42], [:b,43]].each{ |a,b| puts “#{a} =\> #{b}” }

you see the arity of the block of each is indeed something which might  
vary with the usecase.

## HTH Robert

C’est véritablement utile puisque c’est joli.

Antoine de Saint Exupéry

---

<div class="post-metadata">

**Author:** ![dandiebolt](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/a87d85/32.png) [@dandiebolt](https://www.ruby-forum.com/u/dandiebolt)\
**Post date:** [September 12, 2008, 4:30pm UTC](https://www.ruby-forum.com/t/redefe-each-to-include-each-with-index-and-arity-2/148237/8 "2008-09-12T16:30:55Z")

</div>

Thanks for pointing this out. I have two motivations to pursue this:

1. I am interested in more deeply learning all of ruby language  
constructs but I only occasionally write my own classes & iterators. I  
would like to get the the point where I can do this with ease.

2. As a practical matter I often have to modify code I wrote a while ago  
that was originally thrown together for a quick solution to a one of a  
kind problem. So I like to use editing techniques that can quickly  
modify code without of a lot of rework. It may seem trivial, but is sure  
seems to me that adding an index parameter to the each iterator is a lot  
easier than changing the method to each\_with\_index AND adding an index  
parameter. In other words, moving from this code:

a.each do |item|  
Â #process item  
end

to this code:

a.each do |item,index|  
Â #process item & index  
end

is easier to remember and edit than using this code:

a.each\_with\_index do |item,index|

Â #process item & index

end

So if Ruby is such a great dynamic language and DSL (I know it is!)  
there should be a straightforward way to accomplish this despite the  
\*args problem you mention.

So does anyone know how each could be expanded in this fashion to work  
for all enumerable types (ranges, hashes, sets …)?

---

<div class="post-metadata">

**Author:** ![dandiebolt](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/a87d85/32.png) [@dandiebolt](https://www.ruby-forum.com/u/dandiebolt)\
**Post date:** [September 15, 2008, 2:25pm UTC](https://www.ruby-forum.com/t/redefe-each-to-include-each-with-index-and-arity-2/148237/9 "2008-09-15T14:25:08Z")

</div>

2008/9/12 DanDiebolt.exe [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid):

> to this code:
> 
> end
> 
> So if Ruby is such a great dynamic language and DSL (I know it is!) there should be a straightforward way to accomplish this despite the \*args problem you mention.
> 
> So does anyone know how each could be expanded in this fashion to work for all enumerable types (ranges, hashes, sets …)?

I’d rather discourage doing this. If you edit source code to add  
another block parameter then it seems equally easy to replace “each”  
with “each\_with\_index”.

Note that evaluating the arity of the block has some issues because  
for a Hash you usually provide two arguments as in

a\_hash.each do |key, value| # arity 2  
print key, " —\> ", value, “\n”  
end

or one argument as in

a\_hash.each do |\*pair| # arity -1  
p pair  
end

And even to an each\_with\_index for a Hash you can reasonably provide  
two (!) arguments:

irb(main):007:0\> def ar(&b) b.arity end  
=\> nil  
irb(main):008:0\> {“a”=\>“b”}.each\_with\_index {|(k,v),i| p k,v,i}  
“a”  
“b”  
0  
=\> {“a”=\>“b”}  
irb(main):009:0\> ar {|(k,v),i| p k,v,i}  
=\> 2

Kind regards

robert
