6

I'm new to Ruby and am trying to work something out which is confusing me. While writing a simple parser, I found that comparing a char with a == would produce a different result than comparing it with a case expression:

File.open('Quote.txt') do |f|
  f.chars.each do |c|
    puts c == '"' ? 'Quote' : 'Err'

    puts case c
    when '"' then 'QuoteCase'
    else          'ErrCase'
    end

    p c == '"', c === '"', c
  end
end

Assuming Quote.txt is a 1-byte file containing a single quote character (0x22), this produces:

Quote
ErrCase
true
true
"\""

I'm assuming I've done something wrong, but I can't figure out what it is. Can anyone help?

This is in Ruby 1.9.2, by the way.

Jörg W Mittag
  • 363,080
  • 75
  • 446
  • 653
Fuz
  • 235
  • 2
  • 4
  • What is the type of c? And what is the type of "\""? Does `c === "\""` work? – R. Martinho Fernandes Apr 05 '11 at 10:45
  • String, String and yes, in that order. – Fuz Apr 05 '11 at 11:08
  • I took the liberty of making the code a bit more Rubyish (all those backslashes made my eyes bleed :-) ) and add some debugging. – Jörg W Mittag Apr 05 '11 at 11:30
  • I'm stumped. Normally, while I can't necessarily see *what* is wrong, I can at least see *where* something *might* be wrong, but in this case I'm coming up empty. – Jörg W Mittag Apr 05 '11 at 11:34
  • @Jörg Have you tried running the code though? I'm not getting the same output - it works as expected on my machine. – Skilldrick Apr 05 '11 at 11:39
  • @Skilldrick: Yes, I did. I get exactly the output I edited into the question, which is also what the OP got. (In fact, I cut&pasted it.) – Jörg W Mittag Apr 05 '11 at 11:42
  • @Jörg weird. How are you creating your test file? – Skilldrick Apr 05 '11 at 11:47
  • @Skilldrick: A friend of mine tried this out on an old 1.8.6 install that he has, and it works on that. Which version are you running? PS. Sorry for my noob backslash-heavy Ruby syntax. :-( – Fuz Apr 05 '11 at 11:53
  • @Skilldrick: I'm using p180 under Windows, downloaded from rubyinstaller.org. – Fuz Apr 05 '11 at 13:11
  • I get the same output as @Fuz (also on Ruby 1.9.2 on Windows). I noticed c.is_ascii? is false for the case that is going wrong (loaded from single byte file), and c.force_encoding('ASCII') fixes it. Just to reiterate, === behaves as expected but 'case/when' doesn't. – James Hopkin Apr 05 '11 at 13:52

2 Answers2

3

case uses the triple-equal === operator to check each case.

That said, I don't know why your example isn't working:

> c = "\""
> c == "\""
=> true
> c === "\""
=> true

Try removing the .each and explicitly setting c to the quote character and see what happens.

Generally, === is more forgiving than == in Ruby, so I can't imagine a case where == would match and === wouldn't.

Edit: I've just copied your code, with the same input (a file with a single " character) and got the following output:

Quote
QuoteCase
Err
ErrCase

(the last two are from the newline at the end of the file that Vim insists on).

Community
  • 1
  • 1
Skilldrick
  • 69,215
  • 34
  • 177
  • 229
  • If I add a `c = "\"" if c === "\""` line to the top of the block, it works as expected. Also, if I do the same operation with each_char on a string containing a single quote character, rather than reading from a file, it works as expected. Looks like a (fairly fundamental) bug. – Fuz Apr 05 '11 at 11:04
  • I've just tried this out and had no problems - I'm not sure why you're getting this error. – Skilldrick Apr 05 '11 at 11:37
2

It looks like a bug in YARV on windows. I get the correct output in JRuby 1.6.0:

# ruby -v
ruby 1.9.2p180 (2011-02-18) [i386-mingw32]

# ruby test.rb
Quote
ErrCase
true
true
"\""

# jruby --1.9 -v
jruby 1.6.0 (ruby 1.9.2 patchlevel 136) (2011-03-15 f3b6154) (Java HotSpot(TM) Client VM 1.7.0-ea) [Windows XP-x86-java]

# jruby --1.9 test.rb
Quote
QuoteCase
true
true
"\""
Marc-André Lafortune
  • 78,216
  • 16
  • 166
  • 166
Jörg W Mittag
  • 363,080
  • 75
  • 446
  • 653