在 Erlang 中测试集合的相等性
Test equality of sets in Erlang
给定集合的数据结构,测试两个集合的相等性似乎是一项理想的任务,实际上许多实现都允许这样做(例如 python 中的内置集合)。
Erlang 中有不同的集合实现:sets
、ordsets
、gb_sets
。他们的文档没有说明是否可以使用术语比较(“==”)来测试相等性,也没有提供用于测试相等性的显式函数。
一些天真的案例似乎允许使用“==”进行相等性测试,但我有一个更大的应用程序,我可以在其中生成相等的 sets
和 gb_sets
(使用下面的功能),但不要与“==”进行比较。对于 ordsets
,它们总是比较相等。不幸的是,我还没有找到一种方法来为相等集不等于“==”的情况生成最小示例。
为了可靠地测试相等性,我使用以下函数,基于此 theorem on set equality:
%% @doc Compare two sets for equality.
-spec sets_equal(sets:set(), sets:set()) -> boolean().
sets_equal(Set1, Set2) ->
sets:is_subset(Set1, Set2) andalso sets:is_subset(Set2, Set1).
我的问题:
- 他们的理由是什么,为什么 Erlang 集合实现不提供显式相等性测试?
- 对于不同的集合实现,如何解释使用“==”测试集合相等性时的差异?
- 如何生成
sets
的最小示例,其中“==”比较不相等,但给定上述代码,集合相等?
对问题2的一些思考:
sets
的文档指出 "The representation of a set is not defined." 而 ordsets
的文档指出 "An ordset is a representation of a set"。 gb_sets
上的文档没有给出任何类似的指示。
来自 source code of the sets
implementation 的以下评论似乎重申了文档中的声明:
Note that as the order of the keys is undefined we may freely reorder keys within in a bucket.
我的解释是,Erlang 中术语“==”的比较作用于集合的表示,即两个集合只有在它们的表示相同时才比较相等。这将解释不同集合实现的不同行为,但也强化了这个问题,为什么没有明确的相等比较。
ordsets
被实现为一个排序列表,并且实现是相当开放的并且是可见的。他们将比较相等 (==
),尽管 ==
意味着 1.0 等于 1。他们不会比较严格相等 (=:=
)。
sets
以散列 table 的形式实现,其内部表示不适合任何形式的直接比较;当散列冲突发生时,最后添加的元素被添加到给定散列条目的列表中。此前置操作对添加元素的顺序敏感。
gb_sets
被实现为一般的平衡树,树的结构确实取决于元素插入的顺序和重新平衡发生的时间。直接比较它们是不安全的。
要将两个相同类型的集合放在一起比较,一个简单的方法是调用 Mod:is_subset(A,B) andalso Mod:is_subset(B,A)
-- 两个集合只有在相等时才能互为子集。
给定集合的数据结构,测试两个集合的相等性似乎是一项理想的任务,实际上许多实现都允许这样做(例如 python 中的内置集合)。
Erlang 中有不同的集合实现:sets
、ordsets
、gb_sets
。他们的文档没有说明是否可以使用术语比较(“==”)来测试相等性,也没有提供用于测试相等性的显式函数。
一些天真的案例似乎允许使用“==”进行相等性测试,但我有一个更大的应用程序,我可以在其中生成相等的 sets
和 gb_sets
(使用下面的功能),但不要与“==”进行比较。对于 ordsets
,它们总是比较相等。不幸的是,我还没有找到一种方法来为相等集不等于“==”的情况生成最小示例。
为了可靠地测试相等性,我使用以下函数,基于此 theorem on set equality:
%% @doc Compare two sets for equality.
-spec sets_equal(sets:set(), sets:set()) -> boolean().
sets_equal(Set1, Set2) ->
sets:is_subset(Set1, Set2) andalso sets:is_subset(Set2, Set1).
我的问题:
- 他们的理由是什么,为什么 Erlang 集合实现不提供显式相等性测试?
- 对于不同的集合实现,如何解释使用“==”测试集合相等性时的差异?
- 如何生成
sets
的最小示例,其中“==”比较不相等,但给定上述代码,集合相等?
对问题2的一些思考:
sets
的文档指出 "The representation of a set is not defined." 而 ordsets
的文档指出 "An ordset is a representation of a set"。 gb_sets
上的文档没有给出任何类似的指示。
来自 source code of the sets
implementation 的以下评论似乎重申了文档中的声明:
Note that as the order of the keys is undefined we may freely reorder keys within in a bucket.
我的解释是,Erlang 中术语“==”的比较作用于集合的表示,即两个集合只有在它们的表示相同时才比较相等。这将解释不同集合实现的不同行为,但也强化了这个问题,为什么没有明确的相等比较。
ordsets
被实现为一个排序列表,并且实现是相当开放的并且是可见的。他们将比较相等 (==
),尽管 ==
意味着 1.0 等于 1。他们不会比较严格相等 (=:=
)。
sets
以散列 table 的形式实现,其内部表示不适合任何形式的直接比较;当散列冲突发生时,最后添加的元素被添加到给定散列条目的列表中。此前置操作对添加元素的顺序敏感。
gb_sets
被实现为一般的平衡树,树的结构确实取决于元素插入的顺序和重新平衡发生的时间。直接比较它们是不安全的。
要将两个相同类型的集合放在一起比较,一个简单的方法是调用 Mod:is_subset(A,B) andalso Mod:is_subset(B,A)
-- 两个集合只有在相等时才能互为子集。