…but some are more equal than others
I started on this trail because I’m a pedant about spelling, and got stuck on Ruby Monk’s first Boolean exercise.
Why was the following solution invalid >> name.equal?("Bob")
and this solution valid instead? >> name.eql?("Bob")
This set me off researching Ruby equality operators.
There seems to be four types of equality operators:-
’==’
‘.eql?’
‘.equal?’
’===’
And so it would seem, to misquote George Orwell, that some equalities are more equal than others.
==
Simple (or Value) equality.
==
returns true if both sides of the operator have the same value, regardless of datatype.
Thus:
However, the Ruby ==
operator is not quite as forgiving its Javascript counterpart. It does not convert strings to integers, nor does it recognise upper and lower case versions of the same letter as being of the same value.
Therefore:
.eql?
Value and Type Equality
.eql?
has stricter equality criteria than ==
. It tests for equality of value as well as data type.
Hence:
.equal?
Strict (True or Object) Equality
.equal?
has the strictest test of equality*, and is “the most equal of them all”. It tests for equality of object ID.
As a newbie Rubyist at the Flatiron School, I have very recently learnt that all strings (even if identical) have their own individual object ID each time they are written (called?), whereas symbols have a unique and immutable object ID, which will remain each time the symbol is called, even if the value has been reassigned.
The moral of the story was that we should only use symbols (and never strings) as keys in hashes, since they are ‘cheaper’ than strings in terms of memory and performance (in fact, in researching this, I have discovered that object IDs would be another interesting post for another day, but I digress…)
Revenons à nos moutons** - it would seem that this equality test would be passed in fairly limited cases - primarily when symbols or integers are tested against themselves***:
===
Case Equality (or “Subset equality” or “False Equality”)
Okay, so I’ve completely made up the equality names in the parenthesis for this. For that matter, all the equality names for all the other operators are also kind of ‘made-up’ by me, but in those cases, I think they are fairly representative of what those equality operators test for.
===
is generally known everywhere, including in the Ruby documentation, as “Case equality”.
I thought that Techbot and TutorialsPoint gave the best illustrations of the Case Equality usage of ===
, which I will illustrate briefly below:
While I agree with the above usage (it clearly works!), I see things more simplistically. To me, the ===
operator seems to test if the item on right hand side of the operator is a subset of the left hand side of the operator.
For example:
The ===
operator doesn’t seem to test for subset in the cases of strings, arrays and hashes, but it works with Regex:
Anyway, because I think ===
is testing if one element (object?) is a subset of another, I don’t think that it can be considered an equality test at all, hence my nickname of “False Equality” for it.
jtbandes says on StackOverflow that ===
is incredibly useful for implementations in range, regex and proc (and people seem to compare it to the #== operator), but since all that is WAY over my head, I’ll just take his word for it, and you can check it out there.
After all this research, I’m kind of at peace with Ruby’s misspelling of .eql?
, because I can see that it is necessary to differentiate it from .equal?
But I’m still annoyed with elsif
… >:(
Notes:
* In my rather-uninformed opinion (as I’m an absolute newbie), I am more than happy to be enlightened if I’ve made any mistakes in my blog post.
** A French expression for - to get back to the subject. Check out Laura Lawless’s guide to French expressions.
*** I’m finding Object IDs pretty fascinating as I’ve called .object_id on multiple permutations of data types as part of the research for this blog post. I might write about this piece of geekery fascination another day. Also happy to be enlightened/ corrected if I’ve made any mistakes.
Resources:
http://truffles.me.uk/rubys-equality-operator
http://techbot.me/2011/05/ruby-basics-equality-operators-ruby/
http://www.tutorialspoint.com/ruby/ruby_operators.htm
http://ruby-doc.org/core-1.9.3/Object.html
http://stackoverflow.com/questions/7156955/whats-the-difference-between-equal-eql-and