@@ -49,6 +49,7 @@ defmodule Set do
4949 defcallback intersection ( t , t ) :: t
5050 defcallback member? ( t , value ) :: boolean
5151 defcallback put ( t , value ) :: t
52+ defcallback reduce ( t , Enumerable . acc , Enumerable . reducer ) :: Enumerable . result
5253 defcallback size ( t ) :: non_neg_integer
5354 defcallback subset? ( t , t ) :: boolean
5455 defcallback to_list ( t ) :: list ( )
@@ -85,6 +86,10 @@ defmodule Set do
8586 @ doc """
8687 Returns a set that is `set1` without the members of `set2`.
8788
89+ Notice this function is polymorphic as it calculates the difference
90+ for of any type. Each set implementation also provides a `difference`
91+ function, but they can only work with sets of the same type.
92+
8893 ## Examples
8994
9095 iex> Set.difference(HashSet.new([1,2]), HashSet.new([2,3,4])) |> Enum.sort
@@ -93,12 +98,25 @@ defmodule Set do
9398 """
9499 @ spec difference ( t , t ) :: t
95100 def difference ( set1 , set2 ) do
96- target ( set1 ) . difference ( set1 , set2 )
101+ target1 = target ( set1 )
102+ target2 = target ( set2 )
103+
104+ if target1 == target2 do
105+ target1 . difference ( set1 , set2 )
106+ else
107+ target2 . reduce set2 , { :cont , set1 } , fn v , acc ->
108+ { :cont , target1 . delete ( acc , v ) }
109+ end |> elem ( 1 )
110+ end
97111 end
98112
99113 @ doc """
100114 Checks if `set1` and `set2` have no members in common.
101115
116+ Notice this function is polymorphic as it checks for disjoint sets of
117+ any type. Each set implementation also provides a `disjoint?` function,
118+ but they can only work with sets of the same type.
119+
102120 ## Examples
103121
104122 iex> Set.disjoint?(HashSet.new([1, 2]), HashSet.new([3, 4]))
@@ -109,7 +127,19 @@ defmodule Set do
109127 """
110128 @ spec disjoint? ( t , t ) :: boolean
111129 def disjoint? ( set1 , set2 ) do
112- target ( set1 ) . disjoint? ( set1 , set2 )
130+ target1 = target ( set1 )
131+ target2 = target ( set2 )
132+
133+ if target1 == target2 do
134+ target1 . disjoint? ( set1 , set2 )
135+ else
136+ target2 . reduce ( set2 , { :cont , true } , fn member , acc ->
137+ case target1 . member? ( set1 , member ) do
138+ false -> { :cont , acc }
139+ _ -> { :halt , false }
140+ end
141+ end ) |> elem ( 1 )
142+ end
113143 end
114144
115145 @doc """
@@ -121,7 +151,11 @@ defmodule Set do
121151 end
122152
123153 @doc " ""
124- Checks if `set1` and `set2 ` are equal .
154+ Check if two sets are equal using `=== `.
155+
156+ Notice this function is polymorphic as it compares sets of
157+ any type . Each set implementation also provides an `equal? `
158+ function , but they can only work with sets of the same type .
125159
126160 ## Examples
127161
@@ -134,12 +168,28 @@ defmodule Set do
134168 """
135169 @spec equal?(t, t) :: boolean
136170 def equal?(set1, set2) do
137- target(set1).equal?(set1, set2)
171+ target1 = target(set1)
172+ target2 = target(set2)
173+
174+ cond do
175+ target1 == target2 ->
176+ target1.equal?(set1, set2)
177+
178+ target1.size(set1) == target2.size(set2) ->
179+ do_subset?(target1, target2, set1, set2)
180+
181+ true ->
182+ false
183+ end
138184 end
139185
140186 @doc """
141187 Returns a set containing only members in common between `set1` and `set2`.
142188
189+ Notice this function is polymorphic as it calculates the intersection of
190+ any type. Each set implementation also provides a `intersection` function,
191+ but they can only work with sets of the same type.
192+
143193 ## Examples
144194
145195 iex> Set.intersection(HashSet.new([1,2]), HashSet.new([2,3,4])) |> Enum.sort
@@ -151,7 +201,16 @@ defmodule Set do
151201 """
152202 @spec intersection( t, t ) :: t
153203 def intersection ( set1 , set2 ) do
154- target ( set1 ) . intersection ( set1 , set2 )
204+ target1 = target ( set1 )
205+ target2 = target ( set2 )
206+
207+ if target1 == target2 do
208+ target1 . intersection ( set1 , set2 )
209+ else
210+ target1 . reduce set1 , { :cont , target1 . empty ( set1 ) } , fn v , acc ->
211+ { :cont , if ( target2 . member? ( set2 , v ) , do: target1 . put ( acc , v ) , else: acc ) }
212+ end |> elem ( 1 )
213+ end
155214 end
156215
157216 @ doc """
@@ -205,6 +264,10 @@ defmodule Set do
205264 @ doc """
206265 Checks if `set1`'s members are all contained in `set2`.
207266
267+ Notice this function is polymorphic as it checks the subset for
268+ any type. Each set implementation also provides a `subset?` function,
269+ but they can only work with sets of the same type.
270+
208271 ## Examples
209272
210273 iex> Set.subset?(HashSet.new([1, 2]), HashSet.new([1, 2, 3]))
@@ -214,7 +277,14 @@ defmodule Set do
214277 """
215278 @ spec subset? ( t , t ) :: boolean
216279 def subset? ( set1 , set2 ) do
217- target ( set1 ) . subset? ( set1 , set2 )
280+ target1 = target ( set1 )
281+ target2 = target ( set2 )
282+
283+ if target1 == target2 do
284+ target1 . subset? ( set1 , set2 )
285+ else
286+ do_subset? ( target1 , target2 , set1 , set2 )
287+ end
218288 end
219289
220290 @ doc """
@@ -234,6 +304,10 @@ defmodule Set do
234304 @ doc """
235305 Returns a set containing all members of `set1` and `set2`.
236306
307+ Notice this function is polymorphic as it calculates the union of
308+ any type. Each set implementation also provides a `union` function,
309+ but they can only work with sets of the same type.
310+
237311 ## Examples
238312
239313 iex> Set.union(HashSet.new([1,2]), HashSet.new([2,3,4])) |> Enum.sort
@@ -242,7 +316,25 @@ defmodule Set do
242316 """
243317 @ spec union ( t , t ) :: t
244318 def union ( set1 , set2 ) do
245- target ( set1 ) . union ( set1 , set2 )
319+ target1 = target ( set1 )
320+ target2 = target ( set2 )
321+
322+ if target1 == target2 do
323+ target1 . union ( set1 , set2 )
324+ else
325+ target2 . reduce set2 , { :cont , set1 } , fn v , acc ->
326+ { :cont , target1 . put ( acc , v ) }
327+ end |> elem ( 1 )
328+ end
329+ end
330+
331+ defp do_subset?( target1, target2, set1, set2) do
332+ target1. reduce ( set1 , { :cont , true } , fn member , acc ->
333+ case target2 . member? ( set2 , member ) do
334+ true -> { :cont , acc }
335+ _ -> { :halt , false }
336+ end
337+ end ) |> elem ( 1 )
246338 end
247339
248340 defp unsupported_set ( set ) do
0 commit comments