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
on 2012-12-12 12:12
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
on 2012-12-12 12:51
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>
on 2012-12-12 14:36
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
on 2012-12-12 19:12
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
on 2012-12-12 20:55
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
on 2012-12-13 16:55
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
Log in with Google account | Log in with Yahoo account
No account? Register here.