# Array#=== as set equality

**URL:** <https://www.ruby-forum.com/t/array-as-set-equality/194228>\
**Category:** Ruby\
**Created:** [September 1, 2010, 11:04am UTC](https://www.ruby-forum.com/t/array-as-set-equality/194228 "2010-09-01T11:04:29Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![tcsnide](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/t/eb8c5e/32.png) [@tcsnide](https://www.ruby-forum.com/u/tcsnide)\
**Post date:** [September 1, 2010, 11:04am UTC](https://www.ruby-forum.com/t/array-as-set-equality/194228/1 "2010-09-01T11:04:29Z")

</div>

It looks like Array#== and Array#=== are the same. Is that correct?  
That being so, would there be any serious consequences if Array#===  
were redefined to mean “set equality”, e.g.

[:a,:b] === [:b,:a] #=\> true

I can think of a few times that would have been nice to have,  
especially when testing and hashes come into play, the results often  
do not have a fixed order. e.g.

h = {:a=\>1, :b=\>2}  
r = h.map{ |k,v| [k,v] }

assert r == [[:a,1], [:b,2]]

won’t work b/c it might also return

[[:b,2], [:a,1]]

---

<div class="post-metadata">

**Author:** ![tcsnide](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/t/eb8c5e/32.png) [@tcsnide](https://www.ruby-forum.com/u/tcsnide)\
**Post date:** [September 1, 2010, 3:53pm UTC](https://www.ruby-forum.com/t/array-as-set-equality/194228/2 "2010-09-01T15:53:44Z")

</div>

On Wed, Sep 1, 2010 at 11:03 AM, Intransition [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)  
wrote:

> It looks like Array#== and Array#=== are the same. Is that correct?  
> That being so, would there be any serious consequences if Array#===  
> were redefined to mean “set equality”, e.g.  
> I’d prefer  
> assert r == [[:a,1], [:b,2]]  
> yup but in your case could you not do something like

assert\_equal h, Hash[\*r.flatten]

I say that because I’d prefer #=== to have the semantics of include?,  
so that I can do

case some\_value  
when some\_array  
when other\_array  
end

Cheers  
Robert

---

<div class="post-metadata">

**Author:** ![tcsnide](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/t/eb8c5e/32.png) [@tcsnide](https://www.ruby-forum.com/u/tcsnide)\
**Post date:** [September 1, 2010, 5:19pm UTC](https://www.ruby-forum.com/t/array-as-set-equality/194228/3 "2010-09-01T17:19:14Z")

</div>

On Wed, Sep 1, 2010 at 2:03 AM, Intransition [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)  
wrote:

> It looks like Array#== and Array#=== are the same. Is that correct?  
> That being so, would there be any serious consequences if Array#===  
> were redefined to mean “set equality”, e.g.
> 
> Â [:a,:b] === [:b,:a] Â Â #=\> true

Well, it breaks existing code that relies on the existing behavior in  
case statements (don’t know how common that is), and if it was going  
to be redefined, I think it would be more natural to have it reflect  
inclusion (like Range#===) so that, e.g.,

[:a,:b] === :a #=\> true

OTOH, if you need something that is initialized by a value of a  
particular type but provides special match semantics, its pretty  
trivial to do; given the number of different things people might want  
#=== to do on a particular class, and existing code that depends on  
the existing behavior, its usually probably best not to change #===  
for existing (especially core) classes, but just to define matcher  
classes as needed. E.g.,

class OrderInsensitiveArrayMatcher  
def initialize(array)  
@array = array.dup  
end  
def ===(other)  
identity = -\>(x) {x}  
@array.group\_by(&identity) == other.group\_by(&identity)  
rescue  
nil  
end  
end

require ‘set’

class SetMatcher  
def initialize(enum)  
@set = Set.new(enum)  
end  
def ===(other)  
@set == other.to\_set  
rescue  
nil  
end  
end

etc.

If there are common use cases, libraries of useful matchers could be  
built so that everyone isn’t reinventing the wheel, but without  
breaking existing code.

---

<div class="post-metadata">

**Author:** ![tcsnide](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/t/eb8c5e/32.png) [@tcsnide](https://www.ruby-forum.com/u/tcsnide)\
**Post date:** [September 1, 2010, 5:54pm UTC](https://www.ruby-forum.com/t/array-as-set-equality/194228/4 "2010-09-01T17:54:22Z")

</div>

On 09/01/2010 06:49 AM, Robert D. wrote:

> I say that because I’d prefer #=== to have the semantics of include?,  
> so that I can do
> 
> case some\_value  
> when some\_array  
> when other\_array  
> end

Is an asterisk too much typing?

a = [1,2]  
b = [3,4]

case 3  
when \*a; puts “A”  
when \*b; puts “B”  
end

---

<div class="post-metadata">

**Author:** ![tcsnide](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/t/eb8c5e/32.png) [@tcsnide](https://www.ruby-forum.com/u/tcsnide)\
**Post date:** [September 1, 2010, 5:35pm UTC](https://www.ruby-forum.com/t/array-as-set-equality/194228/5 "2010-09-01T17:35:38Z")

</div>

Le 01 septembre à 11:03, Intransition a écrit :

> assert r == [[:a,1], [:b,2]]

Well, you’re talking about set semantics. Why not :

> > r.to\_set == [[:b, 2], [:a, 1]].to\_set  
> > =\> true

?

You could define things like assert\_as\_set which maps the arguments with  
to\_set for you, for instance.

(Note that I’m not a regular user of the unit testing frameworks.)

Fred

---

<div class="post-metadata">

**Author:** ![tcsnide](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/t/eb8c5e/32.png) [@tcsnide](https://www.ruby-forum.com/u/tcsnide)\
**Post date:** [September 1, 2010, 6:23pm UTC](https://www.ruby-forum.com/t/array-as-set-equality/194228/6 "2010-09-01T18:23:39Z")

</div>

On 09/01/2010 09:01 AM, Benoit D. wrote:

> > 
> 
> That is rather cool, I did not know splat was working better than  
> expected here too.
> 
> Thanks,  
> B.D.

Btw, it works in rescue as well.

ALL\_NETWORK\_ERRORS = [Errno::ECONNRESET, Errno::ECONNABORTED,  
Errno::ECONNREFUSED, Errno::EPIPE, IOError, Errno::ETIMEDOUT]

require ‘socket’  
begin  
TCPSocket.new(“localhost”, 9999)  
rescue \*ALL\_NETWORK\_ERRORS =\> ex  
p ex  
end

---

<div class="post-metadata">

**Author:** ![tcsnide](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/t/eb8c5e/32.png) [@tcsnide](https://www.ruby-forum.com/u/tcsnide)\
**Post date:** [September 1, 2010, 6:01pm UTC](https://www.ruby-forum.com/t/array-as-set-equality/194228/7 "2010-09-01T18:01:59Z")

</div>

On 1 September 2010 17:53, Joel VanderWerf [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)  
wrote:

> Is an asterisk too much typing?
> 
> a = [1,2]  
> b = [3,4]
> 
> case 3  
> when \*a; puts “A”  
> when \*b; puts “B”  
> end

That is rather cool, I did not know splat was working better than  
expected here too.

Thanks,  
B.D.
