When does 'dog' not equal 'dog'?

This is more a Ruby than a Rails question – feel free to redirect me
as appropriate – but either this is a Ruby 1.9 bug or I have some
serious misunderstanding. Essentially, I’ve caught the <=> operator
returning nil – not -1, 0, or 1, but nil. Schematically:

class A
attr_accessor :slot
fun matches?(s)
p “s <=> @slot = #{s <=> @slot}”
return (s <=> @slot) == 0
end
end

Driven from a script, I get something like this:

Case 1: Notice that <=> evaluates to nil when it should eval to 0

a.slot = “dog”
a.matches?(“dog”)
"s <=> @slot = "
=> false

Case 2: When I pass a String.new(“dog”) everything works

a.slot = “dog”
a.matches?(String.new(“dog”))
“s <=> @slot = 0”
=> true

What’s really odd is that called interactively, Case 1 works as
expected. When called from a script, it exhibits the oddity above.

Am I missing something fundamental about Ruby and string comparison?

  • ff

fearless_fool wrote:

This is more a Ruby than a Rails question – feel free to redirect me
as appropriate – but either this is a Ruby 1.9 bug or I have some
serious misunderstanding. Essentially, I’ve caught the <=> operator
returning nil – not -1, 0, or 1, but nil. Schematically:

class A
attr_accessor :slot
fun matches?(s)
p “s <=> @slot = #{s <=> @slot}”
return (s <=> @slot) == 0
end
end

Driven from a script, I get something like this:

Case 1: Notice that <=> evaluates to nil when it should eval to 0

a.slot = “dog”
a.matches?(“dog”)
"s <=> @slot = "
=> false

Case 2: When I pass a String.new(“dog”) everything works

a.slot = “dog”
a.matches?(String.new(“dog”))
“s <=> @slot = 0”
=> true

What’s really odd is that called interactively, Case 1 works as
expected. When called from a script, it exhibits the oddity above.

Am I missing something fundamental about Ruby and string comparison?

  • ff

Can’t reproduce with what you’ve given.

ruby-1.9.1-p376 > class A
ruby-1.9.1-p376 ?> attr_accessor :slot
ruby-1.9.1-p376 ?> def matches? s
ruby-1.9.1-p376 ?> puts “s <=> @slot = #{s <=> @slot}”
ruby-1.9.1-p376 ?> (s <=> @slot) == 0
ruby-1.9.1-p376 ?> end
ruby-1.9.1-p376 ?> end
=> nil
ruby-1.9.1-p376 > a = A.new
=> #<A:0x000000041915b8>
ruby-1.9.1-p376 > a.slot = “dog”
=> “dog”
ruby-1.9.1-p376 > a.matches? “dog”
s <=> @slot = 0
=> true
ruby-1.9.1-p376 >

String comparison via <=> to nil will return nil. Are you entirely sure
that in your IRB session your object’s @slot isn’t nil for some reason?

You’ll want to hit the ruby-talk list with this question.

On Feb 10, 2010 7:58 PM, “fearless_fool” [email protected] wrote:

This is more a Ruby than a Rails question – feel free to redirect me
as appropriate – but either this is a Ruby 1.9 bug or I have some
serious misunderstanding. Essentially, I’ve caught the <=> operator
returning nil – not -1, 0, or 1, but nil. Schematically:

class A
attr_accessor :slot
fun matches?(s)
p “s <=> @slot = #{s <=> @slot}”
return (s <=> @slot) == 0
end
end

Driven from a script, I get something like this:

Case 1: Notice that <=> evaluates to nil when it should eval to 0

a.slot = “dog”
a.matches?(“dog”)
"s <=> @slot = "
=> false

Case 2: When I pass a String.new(“dog”) everything works

a.slot = “dog”
a.matches?(String.new(“dog”))
“s <=> @slot = 0”
=> true

What’s really odd is that called interactively, Case 1 works as
expected. When called from a script, it exhibits the oddity above.

Am I missing something fundamental about Ruby and string comparison?

  • ff


You received this message because you are subscribed to the Google
Groups
“Ruby on Rails: Talk” group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to
[email protected][email protected]
.
For more options, visit this group at
http://groups.google.com/group/rubyonrails-talk?hl=en.

On 11 February 2010 00:57, fearless_fool [email protected] wrote:

Essentially, I’ve caught the <=> operator
returning nil – not -1, 0, or 1, but nil. Schematically:

Do you need the <=> operator? (specifically, nothing you’re doing
seems to care whether the compared string is bigger or smaller, only
different. So why not use != instead?

In fact, your matches? method could just as easily be:

def matches?(s)
s == @slot
end

which will return true if they’re equal, or nil if they’re not. If it
has to be true/false, then use !!(s == @slot)

ruby-1.9.1-p376 > a = A.new
=> #<A:0x000000041915b8>
ruby-1.9.1-p376 > a.slot = “dog”
=> “dog”
ruby-1.9.1-p376 > a.matches? “dog”
s <=> @slot = 0
=> true
ruby-1.9.1-p376 >

String comparison via <=> to nil will return nil. Are you entirely sure
that in your IRB session your object’s @slot isn’t nil for some reason?

First, yep, 100% sure that @slot wasn’t nil – I printed it out upon
entering the matches? method. (FWIW, you have it reversed: irb
session worked fine. Driven from a script failed.) Sadly, my
attempts to prune down the example to a reproducible losing case have
failed to fail, so to speak. As suggested by @Matt Brown, I’ll take
this over to the ruby-talk list.

Thanks.