Forum: Ruby Enumerable#zip with File IO

Posted by "林彰史" <hayashi.akifumi.sub@gmail.com> (Guest)
on 2012-12-12 12:12
(Received via mailing list)
Hello,

I found strange behavior of Enumerable#zip, which I could not understand
why.
Appreciate if anyone can explain.

I wrote a short script below to see how Enumerable#zip method works with
File IO.

  file = open( ARGV[0], "r" )
  [1].zip( file.each ) do |n,l| puts "#{n}: #{l}" end
  [2].zip( file.each ) do |n,l| puts "#{n}: #{l}" end

Then, I provided it with a text file:

111
222
333

I expected that its output would be:

1: 111
2: 222

but actually got:

1: 111
2: 333

It looked like the second line of input was accidentally discarded.

If I replaced the arrays with ranges like:

  (1..1).zip( file.each ) do |n,l| puts "#{n}: #{l}" end
  (2..2).zip( file.each ) do |n,l| puts "#{n}: #{l}" end

then I got the expected result.

Ruby version is ruby 1.9.3p327 (2012-11-10 revision 37606)
[x86_64-darwin12.2.1].

Thanks in advance,
Hayashi
Posted by Jan E. (jacques1)
on 2012-12-12 12:36
Hi,

this simply makes no sense. When you go through each line "by hand", the 
"zip" is completely useless. You might as well write

file = open( ARGV[0], "r" )
puts "#{1}: #{file.readline}"
puts "#{2}: #{file.readline}"
...

I guess what you actually want is something like this:

File.foreach(ARGV[0]).with_index do |line, i|
  puts "#{i + 1}: #{line}"
end
Posted by "林彰史" <hayashi.akifumi.sub@gmail.com> (Guest)
on 2012-12-12 12:51
(Received via mailing list)
Yes I agree that it makes no sense, but I wanted to see how zip method
works with File IO with a simple experimental code.
My point is why the second line of input is discarded.

2012/12/12 Jan E. <lists@ruby-forum.com>
Posted by Robert Klemme (robert_k78)
on 2012-12-12 14:36
(Received via mailing list)
On Wed, Dec 12, 2012 at 12:51 PM, 林彰史 <hayashi.akifumi.sub@gmail.com> 
wrote:
> Yes I agree that it makes no sense, but I wanted to see how zip method works
> with File IO with a simple experimental code.
> My point is why the second line of input is discarded.

That might be an artifact of unhealthy using of the Enumerator because
you do not really iterate through the whole file but you use it twice
on the same file.  Chances are that the Enumerator fetches the next
item before it is actually uses and #zip just breaks out of the loop
prematurely.  In your example you'd rather want

[1, 2].zip( file.each ) do |n,l| puts "#{n}: #{l}" end

Or you want to reverse order and do

file.zip([1, 2]) do |l, n| puts "#{n}: #{l}" end

Kind regards

robert
Posted by Bartosz Dziewoński (matmarex)
on 2012-12-12 19:12
(Received via mailing list)
Jan, Robert, yes, but that's not the point.

The same happens with a StringIO:

irb(main):010:0> require 'stringio'
=> true
irb(main):014:0> io = StringIO.new "a\nb\nc\nd\ne"
=> #<StringIO:0x10aee00>
irb(main):015:0> [1].zip(io.each){|a,b| p a,b }
1
"a\n"
=> nil
irb(main):016:0> io.read
=> "c\nd\ne"

I suggest you report a bug on http://bugs.ruby-lang.org/, as this
doesn't look like the correct behavior.

-- Matma Rex
Posted by Robert Klemme (robert_k78)
on 2012-12-12 20:55
(Received via mailing list)
On Wed, Dec 12, 2012 at 7:11 PM, Bartosz Dziewoński 
<matma.rex@gmail.com> wrote:
> "a\n"
> => nil
> irb(main):016:0> io.read
> => "c\nd\ne"
>
> I suggest you report a bug on http://bugs.ruby-lang.org/, as this
> doesn't look like the correct behavior.

I won't do that because first it's an abuse of #zip and second I am
not convinced yet that the behavior is caused by the way streams work.

Kind regards

robert
Posted by "林彰史" <hayashi.akifumi.sub@gmail.com> (Guest)
on 2012-12-13 16:55
(Received via mailing list)
Thanks all,

I have tried the same script with JRuby 1.7.0 also, and I got:

1: 111
2:

Not only the second line but also the third line disappears.
Replacing arrays with ranges did not change the output.
I checked StringIO also and got the same.

So, my conclusion is that Enumerable#zip can be applied to IO
Enumerable object only once, as Robert pointed out. If I accidentally
do it twice, the result of the second application is implementation
dependent.
This is what I did not know.

Regards,
Hayashi



2012/12/13 Robert Klemme <shortcutter@googlemail.com>
Please log in before posting. Registration is free and takes only a minute.
Existing account (Switch to SSL-encrypted connection)
NEW: Do you have a Google/GoogleMail or Yahoo account? No registration required!
Log in with Google account | Log in with Yahoo account
No account? Register here.