enumerator problem in 1.9.1

B

Bug Free

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
 
C

Caleb Clausen

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?
 
R

Robert Klemme

2010/5/31 botp said:
The following line:

=A0 =A0[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,
=A0[5, 7].map.with_index{|v,i| [v,i]}
=3D> [[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 }
=3D> [5, 7]
irb(main):010:0> [5, 7].each_with_index.map {|*v| v }
=3D> [[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]
=3D> nil
irb(main):012:0> [5, 7].each_with_index.each_cons(2) {|*v| p v }
[[5, 7]]
=3D> 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

--=20
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/
 
R

Robert Dober

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.
 
B

botp

2010/5/31 botp said:
The following line:

=A0 =A0[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,
=A0[5, 7].map.with_index{|v,i| [v,i]}
=3D> [[5, 0], [7, 1]]

That's not the proper replacement with map. =A0Rather you'd do:

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

brain dead here.
can you enlighten me on what is "not proper" ? :)

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

kind regards -botp
 
R

Robert Klemme

2010/5/31 botp said:
2010/5/31 botp said:
The following line:

=A0 =A0[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,

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

That's not the proper replacement with map. =A0Rather you'd do:

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

brain dead here.
can you enlighten me on what is "not proper" ? =A0:)

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]
=3D> [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]
=3D> [[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

--=20
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/
 
B

Bug Free

Robert said:
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
 
B

Bug Free

Robert said:
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.
 
B

botp

Because it is closer on what OP initially did:

LOL. ok i get it :)
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
 
R

Robert Klemme

2010/6/1 botp said:
Because it is closer on what OP initially did:

LOL. ok i get it :)
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]

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.
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]

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
 
R

Robert Dober

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

Robert Dober

ruby -ve '[5, 7].each_with_index.each {|a| p a}'
=A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =
=A0 =A0 =A0 =A0 =A0 =A0 =A0 --> =A0|*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 ;)
Cheers
R.



--=20
The best way to predict the future is to invent it.
-- Alan Kay
 
B

Bug Free

Robert said:
I am afraid that is incorrect :(
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]]
 
R

Robert Dober

Robert said:
I am afraid that is incorrect :(
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]]
--
Funny indeed...
 
B

botp

Robert said:
I am afraid that is incorrect :(
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]]
--
Funny indeed...

ah, ok, now i know where i'm confusing myself, and in turn, all of you :)
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 :)

thanks and kind regards -botp
 
R

Robert Dober

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.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,581
Members
45,056
Latest member
GlycogenSupporthealth

Latest Threads

Top