Enumerator problem in 1.9.1

The following line:

[5, 7].each_with_index.each_cons(2) {|v| p v }

prints [5, 7] but I’m expecting [[5, 0], [7, 1]].

Does anyone know how/why this is happening ?

thanks

On 5/30/10, Bug F. [email protected] wrote:

The following line:

[5, 7].each_with_index.each_cons(2) {|v| p v }

prints [5, 7] but I’m expecting [[5, 0], [7, 1]].

Does anyone know how/why this is happening ?

Works for me in 1.9.3. Maybe a 1.9.1 bug?

On Mon, May 31, 2010 at 9:04 AM, Bug F. [email protected] wrote:

The following line:

[5, 7].each_with_index.each_cons(2) {|v| p v }

prints [5, 7] but I’m expecting [[5, 0], [7, 1]].

you’ll have specify the index, eg,

[5, 7].map.with_index{|v,i| [v,i]}
=> [[5, 0], [7, 1]]

kind regards -botp

On Mon, May 31, 2010 at 10:34 AM, Robert K.
[email protected] wrote:

I’d say it’s a bug which seems to be reflected by the fact that it
works as expected in 1.9.3 according to Caleb.
Even more so, as
[5, 7].each_with_index.to_a.each_cons(2) {|v| p v }
[[5, 0], [7, 1]]

Seems quite straight forward to me that the to_a should not change the
semantics.
R.

2010/5/31 botp [email protected]:

=> [[5, 0], [7, 1]]
That’s not the proper replacement with map. Rather you’d do:

irb(main):009:0> [5, 7].each_with_index.map {|v| v }
=> [5, 7]
irb(main):010:0> [5, 7].each_with_index.map {|*v| v }
=> [[5, 0], [7, 1]]

Interestingly the splat operator does not include the index with
#each_cons:

irb(main):011:0> [5, 7].each_with_index.each_cons(2) {|v| p v }
[5, 7]
=> nil
irb(main):012:0> [5, 7].each_with_index.each_cons(2) {|*v| p v }
[[5, 7]]
=> nil

This is on ruby 1.9.1p378 (2010-01-10 revision 26273) [i386-cygwin].

I’d say it’s a bug which seems to be reflected by the fact that it
works as expected in 1.9.3 according to Caleb.

Cheers

robert

On Mon, May 31, 2010 at 4:34 PM, Robert K.
[email protected] wrote:

[5, 7].map.with_index{|v,i| [v,i]}
=> [[5, 0], [7, 1]]

That’s not the proper replacement with map. Rather you’d do:

irb(main):009:0> [5, 7].each_with_index.map {|v| v }
=> [5, 7]
irb(main):010:0> [5, 7].each_with_index.map {|*v| v }
=> [[5, 0], [7, 1]]

brain dead here.
can you enlighten me on what is “not proper” ? :slight_smile:

ie why is each_with_index.map preferable over map.with_index ?

kind regards -botp

2010/5/31 botp [email protected]:

you’ll have specify the index, eg,

brain dead here.
can you enlighten me on what is “not proper” ? :slight_smile:

ie why is each_with_index.map preferable over map.with_index ?

Because it is closer on what OP initially did:

[5, 7].each_with_index.each_cons(2) {|v| p v }

The sequence “[5, 7].each_with_index” returns an Enumerator which must
yield a value and an index on each iteration:

irb(main):001:0> [5, 7].each_with_index.each {|*a| p a}
[5, 0]
[7, 1]
=> [5, 7]

On this Enumerator which #each_cons is invoked.

Contrast that to your suggestion “[5, 7].map.with_index{|v,i| [v,i]}”:
here “[5, 7].map” returns an Enumerator which must yield values only

  • the index is added by “#map_with_index”.

irb(main):002:0> [5, 7].map.each {|*a| p a}
[5]
[7]
=> [[5], [7]]

This means that in your code the index cannot get lost along the way
simply because it is added in the last step and not in the initial
step. Hope it’s clearer now.

Kind regards

robert

Robert D. wrote:

On Mon, May 31, 2010 at 10:34 AM, Robert K.
[email protected] wrote:

I’d say it’s a bug which seems to be reflected by the fact that it
works as expected in 1.9.3 according to Caleb.
Even more so, as
[5, 7].each_with_index.to_a.each_cons(2) {|v| p v }
[[5, 0], [7, 1]]

Seems quite straight forward to me that the to_a should not change the
semantics.
R.

Thanks for all the responses. Where do I pick up 1.9.3 ? I don’t see it
at ftp://ftp.ruby-lang.org/pub/ruby/1.9

Robert D. wrote:

On Mon, May 31, 2010 at 10:34 AM, Robert K.
[email protected] wrote:

I’d say it’s a bug which seems to be reflected by the fact that it
works as expected in 1.9.3 according to Caleb.
Even more so, as
[5, 7].each_with_index.to_a.each_cons(2) {|v| p v }
[[5, 0], [7, 1]]

Seems quite straight forward to me that the to_a should not change the
semantics.
R.

Just checked the just-released 1.9.2-preview3 and it too seems to have
the fix.

On Mon, May 31, 2010 at 9:53 PM, Robert K.
[email protected] wrote:

Because it is closer on what OP initially did:

LOL. ok i get it :slight_smile:
i was just pointing out how to retrieve the index (and the relevance
of it). i wouldn’t want to “give” him the answer because i think
rubyist are programmers…

kind regards -botp

irb(main):001:0> [5, 7].each_with_index.each {|*a| p a}
[5, 0]
[7, 1]
=> [5, 7]

or simply,

=> [5, 7].each_with_index{|*a| p a}
[5, 0]
[7, 1]
=> [5, 7]

This means that in your code the index cannot get lost along the way
simply because it is added in the last step and not in the initial
step.

shouldn’t the programmer be the judge for that?

eg, i can easily scale if i need the square and the index…

[5, 7].map{|a| a*a }.each_with_index{|*a| p a}
[25, 0]
[49, 1]

Kind regards
robert

best regards
-botp

2010/6/1 botp [email protected]:

=> [5, 7]
No, this does not create an intermediate Enumerator. For trying to
hunt down a potential bug this does not help because it leaves the
Enumerator creation totally out of the loop.

[49, 1]
I think we are talking past each other. IMHO this thread is about a
potential bug and you are talking about a solution with regard to
getting an index while iterating.

Cheers

robert

On Tue, Jun 1, 2010 at 4:14 PM, Robert K.
[email protected] wrote:

I think we are talking past each other.

no. it’s me who is talking past. you’re right on really :slight_smile:

IMHO this thread is about a potential bug

indeed. sorry for the noise. arggh.
best regards -botp

I am afraid that is incorrect :frowning:
ruby -ve ‘[5, 7].each_with_index.each {|a| p a}’
ruby 1.9.2dev (2010-05-31 revision 28117) [i686-linux]
5
7

On Tue, Jun 1, 2010 at 11:04 PM, Robert D. [email protected]
wrote:

ruby -ve ‘[5, 7].each_with_index.each {|a| p a}’
→ |*a|

On Tue, Jun 1, 2010 at 5:12 PM, botp [email protected] wrote:

On Tue, Jun 1, 2010 at 11:04 PM, Robert D. [email protected] wrote:

ruby -ve ‘[5, 7].each_with_index.each {|a| p a}’
→ |*a|

I am afraid you lost us again, the bug is that the information is lost
when the splash is not added, e.g. with 1.9.1

ruby -ve ‘[5, 7].each_with_index.each {|*a| p a}’
ruby 1.9.1p378 (2010-01-10 revision 26273) [i686-linux]
[5, 0]
[7, 1]

515/14 > ruby -ve ‘[5, 7].each_with_index.each {|a| p a}’
ruby 1.9.1p378 (2010-01-10 revision 26273) [i686-linux]
5
7

But I admit this one is tricky to follow in such a long thread :wink:
Cheers
R.

Robert D. wrote:

I am afraid that is incorrect :frowning:
ruby -ve ‘[5, 7].each_with_index.each {|a| p a}’
ruby 1.9.2dev (2010-05-31 revision 28117) [i686-linux]
5
7

However, with the each_cons we get:

ruby -ve ‘[5, 7].each_with_index.each_cons(2) {|a| p a}’
ruby 1.9.2dev (2010-05-31 revision 28117) [x86_64-linux]
[[5, 0], [7, 1]]

On Tue, Jun 1, 2010 at 7:32 PM, Bug F. [email protected] wrote:

ruby 1.9.2dev (2010-05-31 revision 28117) [x86_64-linux]
[[5, 0], [7, 1]]

Funny indeed…

On Wed, Jun 2, 2010 at 3:45 AM, Robert D. [email protected]
wrote:

ruby -ve ‘[5, 7].each_with_index.each_cons(2) {|a| p a}’
ruby 1.9.2dev (2010-05-31 revision 28117) [x86_64-linux]
[[5, 0], [7, 1]]

Funny indeed…

ah, ok, now i know where i’m confusing myself, and in turn, all of you
:slight_smile:
i’ve always thought that to capture the index of each_with_index (and
it’s siblings) you’ll have to explicitly specify the index or use the
splat op. this is because (my thoughts only emphasized again) ruby
will passed the whole args to the block splatted (w index as the last
arg), so you’ll have to call the splat again to unsplat it. for
each_cons, the block arg is arrayed/unsplatted, so you get the whole
args. again, just my usual primitive thoughts. Works for me all the
time, and never thought about it again until now. As to whether i
should change the way i think about each_with*, no problem, this is
ruby :slight_smile:

thanks and kind regards -botp

Do not be too harsh with yourself, the semantics of this are
convenient(IMHO) but not necessarily consistent with what one might
expect, if somebody made a CR for the behavior you were expecting I
would probably vote for it.
Cheers
R.