# Each\_with\_index & collect\_with\_index?

**URL:** <https://rubytalk.org/t/each-with-index-collect-with-index/3080>\
**Category:** ruby-talk\
**Created:** [26 November 2002 02:51 UTC](https://rubytalk.org/t/each-with-index-collect-with-index/3080 "2002-11-26T02:51:43Z")\
**Posts on this page:** 14\
**Page:** 2

<div class="post-metadata">

**Author:** ![Martin\_DeMello1](https://avatars.discourse-cdn.com/v4/letter/m/3be4f8/32.png) [@Martin\_DeMello1](https://rubytalk.org/u/Martin_DeMello1)\
**Post date:** [27 November 2002 09:53 UTC](https://rubytalk.org/t/each-with-index-collect-with-index/3080/21 "2002-11-27T09:53:15Z")

</div>

The problem is that Enumerable is built around a class-supplied ‘each’,  
and each itself runs in a very black-box manner, communicating only  
through yield. I don’t see how Enumerable would get the info, short of  
enforcing an each\_with\_index requirement, and rewriting ‘each’ as a  
wrapper around ‘each\_with\_index’.

Perhaps this might work (untested):

module Enumerable  
alias \_each each  
def each  
Enumerable.iteration = 0  
\_each {|\*i|  
Enumerable.iteration += 1  
yield \*i  
}  
end  
end

but note that the number of times you’ve iterated is not necessarily the  
same as what you’d want \_with\_index to return.

martin

> **···**
>
> Alan Chen [alan@digikata.com](mailto:alan@digikata.com) wrote:
> 
> > Well, how about something like Regexp.last\_match, where you can  
> > make a call to retrieve the iteration data.
> > 
> > ary.map { |e,f,g|  
> > ei = Enumerable.iteration\_info  
> > #…  
> > }

---

<div class="post-metadata">

**Author:** ![David\_Alan\_Black1](https://avatars.discourse-cdn.com/v4/letter/d/278dde/32.png) [@David\_Alan\_Black1](https://rubytalk.org/u/David_Alan_Black1)\
**Post date:** [27 November 2002 12:50 UTC](https://rubytalk.org/t/each-with-index-collect-with-index/3080/22 "2002-11-27T12:50:39Z")

</div>

Hi –

> OK… globals = evil… more importantly cryptic code  
> = evil. I can appreciate that. And I think getting  
> rid of the extraneous \_with\_index methods would clean  
> things up a bit.

Heh – I guess you’re not interested in membership in Citizens for MWI  
(map\_with\_indices) 🙂

> But I’m still determined to come up with a solution 😉
> 
> Can we arbitrarily add a parameter to the block?  
> Something like:
> 
> ary.collect {|a,b,c,:iteration| …}
> 
> The idea is if there is an argument beginning with  
> ‘:’, assign the iteration value/object for this  
> particular block to that.

If you want to change the syntax of block variable names, you’ll have  
to get in line and wait your turn 🙂 But the other problem with this  
is that you’re introducing syntax change, just so you don’t have to  
type “\_with\_index”. That’s not a good trade-off.

> That way, block are still easily nestable. As for  
> your other comment… is it really necessary to have  
> an index associated with each argument? Shouldn’t  
> they all be synchronized?

In tinkering with this, the problem I was running into was with nested  
arrays. Let’s say you define Enumerable#imap, which does a map  
operation but also adds an “iteration” method to each object in the  
receiver as it iterates.

a = [[“one”, “two”], [“three”, “four”] ]  
a.imap {|e| puts “we’re at #{e.iteration}”}

But now let’s say you do:

a.imap {|e,f| … }

which assigns the inner array elements to e and f. Now, somewhere  
behind the scenes (in my version), you’re adding the #iteration method  
to the actual objects being iterated. But here, the object – the  
inner array – doesn’t actually appear as itself in the block; it’s  
split across two variables. So you can’t say “e.iteration” or  
“f.iteration”, because the original [e,f] array ([“one”,“two”]) is the  
object that responds to “iteration”.

David

> **···**
>
> On Wed, 27 Nov 2002, Jason Persampieri wrote:
> 
> –  
> David Alan Black  
> home: [dblack@candle.superlink.net](mailto:dblack@candle.superlink.net)  
> work: blackdav@shu.edu  
> Web: [http://pirate.shu.edu/~blackdav](http://pirate.shu.edu/~blackdav)

---

<div class="post-metadata">

**Author:** ![Austin\_Ziegler2](https://avatars.discourse-cdn.com/v4/letter/a/ad7895/32.png) [@Austin\_Ziegler2](https://rubytalk.org/u/Austin_Ziegler2)\
**Post date:** [27 November 2002 14:14 UTC](https://rubytalk.org/t/each-with-index-collect-with-index/3080/23 "2002-11-27T14:14:10Z")

</div>

I like that, sort of. It still has the problem that a global does;  
why not make it an importable method for Enumerable?

ary.map { |e, f, g|  
ei = ary.iteration\_info  
#…  
}

This doesn’t work in cases where the same Enumerable could be  
iterated more than once (either by Threading or by nesting), but I  
think that those are pathological cases anyway.

-austin  
– Austin Ziegler, austin@halostatue.ca on 2002.11.27 at 09.11.52

> **···**
>
> On Wed, 27 Nov 2002 14:51:41 +0900, Alan Chen wrote:
> 
> > On Wed, Nov 27, 2002 at 01:49:10PM +0900, \> [dblack@candle.superlink.net](mailto:dblack@candle.superlink.net) wrote:
> > 
> > > So a new global of that kind probably isn’t on the horizon. I was  
> > > playing around with extending objects during iteration, so that  
> > > you could do:
> > > 
> > > ary.map {|e| puts “We’re at iteration #{e.iteration}”}
> > > 
> > > or something – but I haven’t come up with a way to do it that  
> > > fits more than a subset of cases. For one thing, you can’t extend  
> > > Fixnums, so anything based on that method won’t work if your  
> > > array contains those. Also, the syntax of block parameters makes  
> > > it hard: if you have
> > > 
> > > ary.map {|e,f,g| … }
> > > 
> > > I’m not sure there’s a way to determine which object got the  
> > > #iteration method added to it…  
> > > Well, how about something like Regexp.last\_match, where you can  
> > > make a call to retrieve the iteration data.
> > 
> > ary.map { |e,f,g|  
> > ei = Enumerable.iteration\_info  
> > #…  
> > }

---

<div class="post-metadata">

**Author:** ![ts1](https://avatars.discourse-cdn.com/v4/letter/t/a8b319/32.png) [@ts1](https://rubytalk.org/u/ts1)\
**Post date:** [27 November 2002 10:06 UTC](https://rubytalk.org/t/each-with-index-collect-with-index/3080/24 "2002-11-27T10:06:46Z")

</div>

> &nbsp;&nbsp;def each  
> &nbsp;&nbsp;&nbsp;&nbsp;Enumerable.iteration = 0

and if someone write :

&nbsp;&nbsp;&nbsp;[[1, 2], [3, 4]].each {|i| i.each {|j| ... }}

Guy Decoux

---

<div class="post-metadata">

**Author:** ![David\_Alan\_Black1](https://avatars.discourse-cdn.com/v4/letter/d/278dde/32.png) [@David\_Alan\_Black1](https://rubytalk.org/u/David_Alan_Black1)\
**Post date:** [27 November 2002 14:19 UTC](https://rubytalk.org/t/each-with-index-collect-with-index/3080/25 "2002-11-27T14:19:26Z")

</div>

Hi –

> **···**
>
> On Wed, 27 Nov 2002, Austin Ziegler wrote:
> 
> > On Wed, 27 Nov 2002 14:51:41 +0900, Alan Chen wrote:
> > 
> > > ary.map { |e,f,g|  
> > > ei = Enumerable.iteration\_info  
> > > #…  
> > > }
> > 
> > I like that, sort of. It still has the problem that a global does;  
> > why not make it an importable method for Enumerable?
> > 
> > ary.map { |e, f, g|  
> > ei = ary.iteration\_info  
> > #…  
> > }
> > 
> > This doesn’t work in cases where the same Enumerable could be  
> > iterated more than once (either by Threading or by nesting), but I  
> > think that those are pathological cases anyway.
> 
> Not necessarily… but also, given that all of this is to avoid  
> either \*\_with\_index or a manually-incremented loop variable, it’s  
> probably not worth having it equate to a decision that certain other  
> constructs (threading or nesting) are to be avoided.
> 
> David
> 
> –  
> David Alan Black  
> home: [dblack@candle.superlink.net](mailto:dblack@candle.superlink.net)  
> work: blackdav@shu.edu  
> Web: [http://pirate.shu.edu/~blackdav](http://pirate.shu.edu/~blackdav)

---

<div class="post-metadata">

**Author:** ![ts1](https://avatars.discourse-cdn.com/v4/letter/t/a8b319/32.png) [@ts1](https://rubytalk.org/u/ts1)\
**Post date:** [27 November 2002 14:19 UTC](https://rubytalk.org/t/each-with-index-collect-with-index/3080/26 "2002-11-27T14:19:31Z")

</div>

> This doesn't work in cases where the same Enumerable could be  
> iterated more than once (either by Threading or by nesting), but I  
> think that those are pathological cases anyway.

Why it's pathologic to iterate on the same object in 2 different threads ?

Guy Decoux

---

<div class="post-metadata">

**Author:** ![Tim\_Bates](https://avatars.discourse-cdn.com/v4/letter/t/3da27b/32.png) [@Tim\_Bates](https://rubytalk.org/u/Tim_Bates)\
**Post date:** [27 November 2002 14:35 UTC](https://rubytalk.org/t/each-with-index-collect-with-index/3080/27 "2002-11-27T14:35:58Z")

</div>

I think this has been suggested before, but… why not use something like  
Enumerable.index? But here’s the new bit, just have it refer to the innermost  
iterator. You can assign it to something if you want nested iterators, eg:

arr.each do |e|  
outerindex = Enumerable.index  
arr.each do |f|  
innerindex = Enumerable.index  
…  
end  
end

And perhaps Enumerable.index == nil if we’re not inside an iterator.

Only problem I can see is if I were to define my own iterator using ‘yield’,  
how would I indicate that I want Enumerable.index to return something  
sensible?

Tim Bates

> **···**
>
> On Wed, 27 Nov 2002 11:20 pm, [dblack@candle.superlink.net](mailto:dblack@candle.superlink.net) wrote:
> 
> > Now, somewhere behind the scenes (in my version), you’re adding the  
> > #iteration method to the actual objects being iterated.
> 
> –  
> tim@bates.id.au

---

<div class="post-metadata">

**Author:** ![HAL\_9000](https://avatars.discourse-cdn.com/v4/letter/h/90ced4/32.png) [@HAL\_9000](https://rubytalk.org/u/HAL_9000)\
**Post date:** [27 November 2002 16:04 UTC](https://rubytalk.org/t/each-with-index-collect-with-index/3080/28 "2002-11-27T16:04:01Z")

</div>

[snippage]

> which assigns the inner array elements to e and f. Now, somewhere  
> behind the scenes (in my version), you’re adding the #iteration method  
> to the actual objects being iterated. But here, the object – the  
> inner array – doesn’t actually appear as itself in the block; it’s  
> split across two variables. So you can’t say “e.iteration” or  
> “f.iteration”, because the original [e,f] array ([“one”,“two”]) is the  
> object that responds to “iteration”.

David,

Adding singletons to the iterator variable was  
a path that I went down once… it had some  
drawbacks, e.g., no Fixnums and overhead of  
adding a singleton to _each object_.

Now that you’ve been playing with this some,  
what are your thoughts on my “super-iterator”  
from a few months back?

One of the problems it tried to solve was  
subsuming #each\_with\_index into #each by  
making every iterator object a special  
object with an accessor method; if the  
value changed, it would be stored back  
in the original collection.

Someone will (correctly) protest that this  
doesn’t replace every usage of #each\_with\_index.

But (personally) my most common use of it is when  
I need to replace or change an element in an  
array while I’m iterating.

Hal

> **···**
>
> ----- Original Message -----  
> From: [dblack@candle.superlink.net](mailto:dblack@candle.superlink.net)  
> To: “ruby-talk ML” [ruby-talk@ruby-lang.org](mailto:ruby-talk@ruby-lang.org)  
> Sent: Wednesday, November 27, 2002 6:50 AM  
> Subject: Re: each\_with\_index & collect\_with\_index?

---

<div class="post-metadata">

**Author:** ![Martin\_DeMello1](https://avatars.discourse-cdn.com/v4/letter/m/3be4f8/32.png) [@Martin\_DeMello1](https://rubytalk.org/u/Martin_DeMello1)\
**Post date:** [27 November 2002 13:13 UTC](https://rubytalk.org/t/each-with-index-collect-with-index/3080/29 "2002-11-27T13:13:32Z")

</div>

Doh! What _is_ the correct thing to do in such a case, without having to  
introduce special syntax? Best I can think of is to have  
Enumerable.iteration return a stack, which would be inconvenient to use.  
Or maybe maintain a stack internally, but have a separate accessor for  
the top of the stack (i.e. the innermost block count)

That might work out, actually

module Enumerable

def count  
(@@iteration ||= ).last  
end

def counts  
@@iteration or   
end

alias \_each each  
def each  
(@@iteration ||= ).push(0)  
\_each {|\*i|  
@@iteration.last += 1  
yield \*i  
}  
@@iteration.pop  
end  
end

Another random thought: can you get at the names of the block local  
variables? Might be possible to hack something up along the lines of a  
hash of symbols, if so.

martin

> **···**
>
> ts [decoux@moulon.inra.fr](mailto:decoux@moulon.inra.fr) wrote:
> 
> > > def each  
> > > Enumerable.iteration = 0
> > 
> > and if someone write :
> > 
> > [[1, 2], [3, 4]].each {|i| i.each {|j| … }}

---

<div class="post-metadata">

**Author:** ![Ara.T.Howard1](https://avatars.discourse-cdn.com/v4/letter/a/f19dbf/32.png) [@Ara.T.Howard1](https://rubytalk.org/u/Ara.T.Howard1)\
**Post date:** [27 November 2002 16:11 UTC](https://rubytalk.org/t/each-with-index-collect-with-index/3080/30 "2002-11-27T16:11:37Z")

</div>

> arr.each do |e|  
> outerindex = Enumerable.index  
> arr.each do |f|  
> innerindex = Enumerable.index  
> …  
> end  
> end

this is all very straight forward using an Enumerable::Iterator, i had to add  
only two lines to the class to accomplish this :

arr = %w(zero one two)  
a = arr.iterator  
a.each do |ea|  
print “a.index(#{a.index}) → ea : #{ea}\n\t”  
b = arr.iterator  
b.each do |eb|  
print "b.index(#{b.index}) → eb : #{eb}, "  
end  
print “\n”  
end

> >

a.index(0) → ea : zero  
b.index(0) → eb : zero, b.index(1) → eb : one, b.index(2) → eb : two,  
a.index(1) → ea : one  
b.index(0) → eb : zero, b.index(1) → eb : one, b.index(2) → eb : two,  
a.index(2) → ea : two  
b.index(0) → eb : zero, b.index(1) → eb : one, b.index(2) → eb : two,

[http://eli.fsl.noaa.gov/lib/ruby/site\_ruby/1.6/enumerable.rb](http://eli.fsl.noaa.gov/lib/ruby/site_ruby/1.6/enumerable.rb)

-a

> **···**
>
> On Wed, 27 Nov 2002, Tim Bates wrote:
> 
> –
> 
> ====================================
> 
> > Ara Howard  
> > NOAA Forecast Systems Laboratory  
> > Information and Technology Services  
> > Data Systems Group  
> > R/FST 325 Broadway  
> > Boulder, CO 80305-3328  
> > Email: [ahoward@fsl.noaa.gov](mailto:ahoward@fsl.noaa.gov)  
> > Phone: 303-497-7238  
> > Fax: 303-497-7259  
> > ====================================

---

<div class="post-metadata">

**Author:** ![David\_Alan\_Black1](https://avatars.discourse-cdn.com/v4/letter/d/278dde/32.png) [@David\_Alan\_Black1](https://rubytalk.org/u/David_Alan_Black1)\
**Post date:** [27 November 2002 16:49 UTC](https://rubytalk.org/t/each-with-index-collect-with-index/3080/31 "2002-11-27T16:49:44Z")

</div>

Hi –

> From: [dblack@candle.superlink.net](mailto:dblack@candle.superlink.net)  
> To: “ruby-talk ML” [ruby-talk@ruby-lang.org](mailto:ruby-talk@ruby-lang.org)  
> Sent: Wednesday, November 27, 2002 6:50 AM  
> Subject: Re: each\_with\_index & collect\_with\_index?
> 
> [snippage]
> 
> > which assigns the inner array elements to e and f. Now, somewhere  
> > behind the scenes (in my version), you’re adding the #iteration method  
> > to the actual objects being iterated. But here, the object – the  
> > inner array – doesn’t actually appear as itself in the block; it’s  
> > split across two variables. So you can’t say “e.iteration” or  
> > “f.iteration”, because the original [e,f] array ([“one”,“two”]) is the  
> > object that responds to “iteration”.
> 
> David,
> 
> Adding singletons to the iterator variable was  
> a path that I went down once… it had some  
> drawbacks, e.g., no Fixnums and overhead of  
> adding a singleton to _each object_.
> 
> Now that you’ve been playing with this some,  
> what are your thoughts on my “super-iterator”  
> from a few months back?

Yes, I was reminiscing about that, and realizing that I was  
semi-reinventing it 🙂 But I just can’t find the right “home” for an  
internal iteration counter. Extending the object has so many  
problems, and the various global techniques are, well, global.

One thing I believe is missing, conceptually speaking, is the ability  
on the part of a proc or code block to capture a reference to itself  
from inside itself. If it could, then each block could be extended to  
have a counter for itself. I think. Maybe. That’s the only avenue I  
can think of to go down which doesn’t feel like it’s stacking too much  
info into too little namespace. Then again, it might not be thread  
safe. But it could report out its counter based on a thread-based  
hash…

David

> **···**
>
> On Thu, 28 Nov 2002, Hal E. Fulton wrote:
> 
> > ----- Original Message -----
> 
> –  
> David Alan Black  
> home: [dblack@candle.superlink.net](mailto:dblack@candle.superlink.net)  
> work: blackdav@shu.edu  
> Web: [http://pirate.shu.edu/~blackdav](http://pirate.shu.edu/~blackdav)

---

<div class="post-metadata">

**Author:** ![ts1](https://avatars.discourse-cdn.com/v4/letter/t/a8b319/32.png) [@ts1](https://rubytalk.org/u/ts1)\
**Post date:** [27 November 2002 13:21 UTC](https://rubytalk.org/t/each-with-index-collect-with-index/3080/32 "2002-11-27T13:21:46Z")

</div>

> module Enumerable

I don't think that you can put it in a module, or a class.  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;

> Another random thought: can you get at the names of the block local  
> variables? Might be possible to hack something up along the lines of a  
> hash of symbols, if so.

#local\_variables give you the name of all local variables (with block  
&nbsp;&nbsp;local) but you'll have a problem (like your current implementation) when  
&nbsp;&nbsp;I'll introduce threads :-))

Guy Decoux

---

<div class="post-metadata">

**Author:** ![Ara.T.Howard1](https://avatars.discourse-cdn.com/v4/letter/a/f19dbf/32.png) [@Ara.T.Howard1](https://rubytalk.org/u/Ara.T.Howard1)\
**Post date:** [27 November 2002 17:28 UTC](https://rubytalk.org/t/each-with-index-collect-with-index/3080/33 "2002-11-27T17:28:29Z")

</div>

[snip]

> One thing I believe is missing, conceptually speaking, is the ability  
> on the part of a proc or code block to capture a reference to itself  
> from inside itself.  
> [snip]

is this not what this does?

[snip]  
def initialize\_fetch\_block  
@index = -1  
callcc do |@after\_fetch|  
@has\_next = true  
@enumerable.each do |@next\_element|  
callcc do |@next\_fetch| @after\_fetch.call end  
end  
@has\_next = false  
@next\_fetch = nil  
@after\_fetch.call  
end  
@after\_fetch = nil  
end

```
def fetch_next_element
  result = @next_element
  @index = @index + 1
  callcc do |@after_fetch| @next_fetch.call end
  @after_fetch = nil
  result
end

```

[snip]

@next\_fetch and @after\_fetch are referencess to blocks captured from inside  
blocks?

-a

> **···**
>
> On Thu, 28 Nov 2002 [dblack@candle.superlink.net](mailto:dblack@candle.superlink.net) wrote:
> 
> –
> 
> ====================================
> 
> > Ara Howard  
> > NOAA Forecast Systems Laboratory  
> > Information and Technology Services  
> > Data Systems Group  
> > R/FST 325 Broadway  
> > Boulder, CO 80305-3328  
> > Email: [ahoward@fsl.noaa.gov](mailto:ahoward@fsl.noaa.gov)  
> > Phone: 303-497-7238  
> > Fax: 303-497-7259  
> > ====================================

---

<div class="post-metadata">

**Author:** ![Martin\_DeMello1](https://avatars.discourse-cdn.com/v4/letter/m/3be4f8/32.png) [@Martin\_DeMello1](https://rubytalk.org/u/Martin_DeMello1)\
**Post date:** [27 November 2002 14:54 UTC](https://rubytalk.org/t/each-with-index-collect-with-index/3080/34 "2002-11-27T14:54:02Z")

</div>

> > module Enumerable
> 
> I don’t think that you can put it in a module, or a class.

Where would I put it, then? Global is obviously out, and I can’t think  
of any object I could attach the countstack to. Maybe an instance of a  
CountStack class, with Kernel methods to access the stack.

> > Another random thought: can you get at the names of the block local  
> > variables? Might be possible to hack something up along the lines of a  
> > hash of symbols, if so.
> 
> #local\_variables give you the name of all local variables (with block  
> local) but you’ll have a problem (like your current implementation) when  
> I’ll introduce threads :-))

Ah, threads 🙂 Is there a way of writing a class so that I can have only  
one CountStack object per thread, but each thread has its own instance?

martin

> **···**
>
> ts [decoux@moulon.inra.fr](mailto:decoux@moulon.inra.fr) wrote:

[Previous page](https://rubytalk.org/t/each-with-index-collect-with-index/3080.md?page=1)
