Skip to content

Commit 15d2d9f

Browse files
author
José Valim
committed
Impose === as the operator in the Set API
1 parent a31f180 commit 15d2d9f

File tree

4 files changed

+66
-19
lines changed

4 files changed

+66
-19
lines changed

lib/elixir/lib/hash_set.ex

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,8 @@ defmodule HashSet do
3838
import Bitwise
3939

4040
@compile :inline_list_funcs
41-
@compile { :inline, bucket_hash: 1, bucket_index: 1, bucket_nth_index: 2, bucket_next: 1 }
41+
@compile { :inline, bucket_hash: 1, bucket_index: 1, bucket_nth_index: 2,
42+
bucket_next: 1, bucket_member?: 2 }
4243

4344
@doc """
4445
Creates a new empty set.
@@ -188,11 +189,11 @@ defmodule HashSet do
188189
end
189190

190191
defp set_member?(ordered(bucket: bucket), member) do
191-
:lists.member(member, bucket)
192+
bucket_member?(member, bucket)
192193
end
193194

194195
defp set_member?(trie(root: root, depth: depth), member) do
195-
:lists.member(member, node_bucket(root, depth, bucket_hash(member)))
196+
bucket_member?(member, node_bucket(root, depth, bucket_hash(member)))
196197
end
197198

198199
defp set_delete(ordered(bucket: bucket, size: size) = set, member) do
@@ -260,6 +261,10 @@ defmodule HashSet do
260261

261262
## Bucket helpers
262263

264+
defp bucket_member?(k, [k|_]), do: true
265+
defp bucket_member?(k, [_|t]), do: bucket_member?(k, t)
266+
defp bucket_member?(_k, []), do: false
267+
263268
defp bucket_filter([e|bucket], fun, acc, count) do
264269
case fun.(e) do
265270
true -> bucket_filter(bucket, fun, [e|acc], count)
@@ -476,13 +481,6 @@ defmodule HashSet do
476481
defp each_contract(acc, [m|bucket]), do: [m|each_contract(acc, bucket)]
477482
defp each_contract([], bucket), do: bucket
478483
defp each_contract(acc, []), do: acc
479-
480-
@doc false
481-
def inspect_depth(trie(depth: d)), do: d
482-
@doc false
483-
def inspect_contract(trie(contract_on: c)), do: c
484-
@doc false
485-
def inspect_expand(trie(expand_on: e)), do: e
486484
end
487485

488486
defimpl Enumerable, for: HashSet do

lib/elixir/lib/set.ex

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,21 @@ defmodule Set do
1515
For simplicity's sake, in the examples below every time
1616
`new` is used, it implies one of the module-specific
1717
calls like above.
18+
19+
## Protocols
20+
21+
Sets are required to implement the `Enumerable` protocol,
22+
allowing one to write:
23+
24+
Enum.each(set, fn k ->
25+
IO.inspect k
26+
end)
27+
28+
## Match
29+
30+
Sets are required to implement all operations
31+
using the match (`===`) operator. Any deviation from
32+
this behaviour should be avoided and explicitly documented.
1833
"""
1934

2035
use Behaviour

lib/elixir/test/elixir/hash_set_test.exs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,10 +40,8 @@ defmodule HashSetTest do
4040
diff = HashSet.difference(filled_set(9000), filled_set(9000))
4141
assert HashSet.equal?(diff, HashSet.new([]))
4242

43-
#Ensure the trie has correctly resized
44-
assert HashSet.inspect_depth(diff) == 0
45-
assert HashSet.inspect_contract(diff) == 2
46-
assert HashSet.inspect_expand(diff) == 80
43+
# Ensure the trie has correctly resized
44+
assert { HashSet, 0, 0, 80, 2, _ } = diff
4745
end
4846

4947
test "member? with ordered sets" do

lib/elixir/test/elixir/set_test.exs

Lines changed: 41 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,21 @@ defmodule SetTest.Common do
1414
assert Set.equal?(result, new_set([1, 3]))
1515
end
1616

17+
test :delete_with_match do
18+
refute Set.member?(Set.delete(int_set, 1), 1)
19+
assert Set.member?(Set.delete(int_set, 1.0), 1)
20+
end
21+
1722
test :difference do
1823
result = Set.difference(new_set([1, 2, 3]), new_set([3]))
1924
assert Set.equal?(result, HashSet.new([1, 2]))
2025
end
2126

27+
test :difference_with_match do
28+
refute Set.member?(Set.difference(int_set, new_set([1])), 1)
29+
assert Set.member?(Set.difference(int_set, new_set([1.0])), 1)
30+
end
31+
2232
test :disjoint? do
2333
assert Set.disjoint?(new_set([1, 2, 3]), new_set([4, 5 ,6])) == true
2434
assert Set.disjoint?(new_set([1, 2, 3]), new_set([3, 4 ,5])) == false
@@ -30,31 +40,48 @@ defmodule SetTest.Common do
3040
end
3141

3242
test :equal? do
33-
assert Set.equal?(new_set([1, 2, 3]), new_set([3, 2, 1])) == true
43+
assert Set.equal?(new_set([1, 2, 3]), new_set([3, 2, 1]))
44+
refute Set.equal?(new_set([1, 2, 3]), new_set([3.0, 2.0, 1.0]))
3445
end
3546

3647
test :intersection do
3748
result = Set.intersection(new_set([1, 2, 3]), new_set([2, 3, 4]))
3849
assert Set.equal?(result, new_set([2, 3]))
3950
end
4051

52+
test :intersection_with_match do
53+
assert Set.member?(Set.intersection(int_set, new_set([1])), 1)
54+
refute Set.member?(Set.intersection(int_set, new_set([1.0])), 1)
55+
end
56+
4157
test :member? do
42-
assert Set.member?(new_set([1, 2, 3]), 2) == true
43-
assert Set.member?(new_set([1, 2, 3]), 4) == false
58+
assert Set.member?(new_set([1, 2, 3]), 2)
59+
refute Set.member?(new_set([1, 2, 3]), 4)
60+
refute Set.member?(new_set([1, 2, 3]), 1.0)
4461
end
4562

4663
test :put do
4764
result = Set.put(new_set([1, 2]), 3)
4865
assert Set.equal?(result, new_set([1, 2, 3]))
4966
end
5067

68+
test :put_with_match do
69+
assert Set.size(Set.put(int_set, 1)) == 3
70+
assert Set.size(Set.put(int_set, 1.0)) == 4
71+
end
72+
5173
test :size do
5274
assert Set.size(new_set([1, 2, 3])) == 3
5375
end
5476

5577
test :subset? do
56-
assert Set.subset?(new_set([1, 2]), new_set([1, 2, 3])) == true
57-
assert Set.subset?(new_set([1, 2, 3]), new_set([1, 2])) == false
78+
assert Set.subset?(new_set([1, 2]), new_set([1, 2, 3]))
79+
refute Set.subset?(new_set([1, 2, 3]), new_set([1, 2]))
80+
end
81+
82+
test :subset_with_match? do
83+
assert Set.subset?(new_set([1]), int_set)
84+
refute Set.subset?(new_set([1.0]), int_set)
5885
end
5986

6087
test :to_list do
@@ -66,6 +93,11 @@ defmodule SetTest.Common do
6693
assert Set.equal?(result, new_set([1, 2, 3, 4]))
6794
end
6895

96+
test :union_with_match do
97+
assert Set.size(Set.union(int_set, new_set([1]))) == 3
98+
assert Set.size(Set.union(int_set, new_set([1.0]))) == 4
99+
end
100+
69101
test "unsupported set" do
70102
assert_raise ArgumentError, "unsupported set: :bad_set", fn ->
71103
Set.to_list :bad_set
@@ -75,6 +107,10 @@ defmodule SetTest.Common do
75107
defp new_set(list // []) do
76108
unquote(module).new(list)
77109
end
110+
111+
defp int_set() do
112+
unquote(module).new([1,2,3])
113+
end
78114
end
79115
end
80116
end

0 commit comments

Comments
 (0)