# When does 'dog' not equal 'dog'?

**URL:** <https://www.ruby-forum.com/t/when-does-dog-not-equal-dog/183274>\
**Category:** Rails\
**Created:** [February 11, 2010, 1:58am UTC](https://www.ruby-forum.com/t/when-does-dog-not-equal-dog/183274 "2010-02-11T01:58:55Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![fearless\_fool](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/f/5e9695/32.png) [@fearless\_fool](https://www.ruby-forum.com/u/fearless_fool)\
**Post date:** [February 11, 2010, 1:58am UTC](https://www.ruby-forum.com/t/when-does-dog-not-equal-dog/183274/1 "2010-02-11T01:58:55Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![fearless\_fool](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/f/5e9695/32.png) [@fearless\_fool](https://www.ruby-forum.com/u/fearless_fool)\
**Post date:** [February 11, 2010, 2:21am UTC](https://www.ruby-forum.com/t/when-does-dog-not-equal-dog/183274/2 "2010-02-11T02:21:19Z")

</div>

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?

---

<div class="post-metadata">

**Author:** ![fearless\_fool](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/f/5e9695/32.png) [@fearless\_fool](https://www.ruby-forum.com/u/fearless_fool)\
**Post date:** [February 11, 2010, 2:21am UTC](https://www.ruby-forum.com/t/when-does-dog-not-equal-dog/183274/3 "2010-02-11T02:21:45Z")

</div>

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

On Feb 10, 2010 7:58 PM, “fearless\_fool” [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) 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 removed\_email\_address@domain.invalid.  
To unsubscribe from this group, send email to  
removed\_email\_address@domain.invalid[removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)  
.  
For more options, visit this group at  
[http://groups.google.com/group/rubyonrails-talk?hl=en](http://groups.google.com/group/rubyonrails-talk?hl=en).

---

<div class="post-metadata">

**Author:** ![fearless\_fool](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/f/5e9695/32.png) [@fearless\_fool](https://www.ruby-forum.com/u/fearless_fool)\
**Post date:** [February 11, 2010, 10:07am UTC](https://www.ruby-forum.com/t/when-does-dog-not-equal-dog/183274/4 "2010-02-11T10:07:39Z")

</div>

On 11 February 2010 00:57, fearless\_fool [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) 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)

---

<div class="post-metadata">

**Author:** ![fearless\_fool](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/f/5e9695/32.png) [@fearless\_fool](https://www.ruby-forum.com/u/fearless_fool)\
**Post date:** [February 11, 2010, 2:59am UTC](https://www.ruby-forum.com/t/when-does-dog-not-equal-dog/183274/5 "2010-02-11T02:59:12Z")

</div>

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