List 如何在不比较完整列表的情况下检测列表更改

List 如何在不比较完整列表的情况下检测列表更改,list,erlang,List,Erlang,我有一个函数,如果自生成此术语/列表以来,它正在使用的术语/列表有任何更改,则该函数将失败。我希望避免检查每个参数是否仍然相同。因此,每次生成术语/列表以执行CRC或类似操作时,我都会考虑。在使用它之前,我会再次生成CRC,这样我可以99999%确定术语/列表仍然相同 关于一个特殊的答案,我正在用Erlang编程,我正在考虑使用以下类型的函数: -spec(list_crc32(List :: [term()]) -> CRC32 :: integer()). 我使用这个术语,因为它是一

我有一个函数,如果自生成此术语/列表以来,它正在使用的术语/列表有任何更改,则该函数将失败。我希望避免检查每个参数是否仍然相同。因此,每次生成术语/列表以执行CRC或类似操作时,我都会考虑。在使用它之前,我会再次生成CRC,这样我可以99999%确定术语/列表仍然相同

关于一个特殊的答案,我正在用Erlang编程,我正在考虑使用以下类型的函数:

-spec(list_crc32(List :: [term()]) -> CRC32 :: integer()).
我使用这个术语,因为它是一个术语列表(erlang已经有一个默认的快速CRC库,但用于二进制值)。我已经考虑使用<代码>“Erlang:CRC32(TyMytoTo-二进制(术语))”< /C> >,但不确定是否有更好的方法。

你觉得怎么样?
尊敬的Borja。

如果没有更多的上下文,就有点难以理解为什么会出现这个问题,特别是因为Erlang术语是不可变的——一旦赋值,任何其他操作都不能更改变量的值,即使在同一个函数中也是如此

<> >如果你的问题是“我如何快速断言<代码>真的= a==a < /代码>?”然后考虑这个代码:

A = generate_list()
% other things in this function happen
A = A.
上面的代码片段总是断言
A
仍然是
A
,因为不可能像在Python中那样更改A

如果您的问题是“如何断言一个新列表的值生成的值与另一个已知列表的值完全相同?”则使用匹配或实际断言是最快的方法:

start() ->
    A = generate_list(),
    assert_loop(A).

assert_loop(A) ->
    ok = do_stuff(),
    A = generate_list(),
    assert_loop(A).
上面的
assert\u loop/1
函数强制断言
generate\u list/0
的输出仍然是A。不知道系统中可能发生的其他事情会影响该函数的结果,但行
A=generate\u list()如果返回的列表与
A
的值不完全相同,则
将崩溃

事实上,在本例中,无论执行多少次上述
assert\u loop/1
,都无法更改
A

现在考虑一种不同的风格:

compare_loop(A) ->
    ok = do_stuff(),
    case A =:= generate_list() of
        true  -> compare_loop(A);
        false -> terminate_gracefully()
    end.
在这里,我们为自己提供了除崩溃之外的其他选择,但效果最终是相同的,因为
=:=
不仅仅是一个相等的测试,它是一个匹配测试,意味着这两个值的计算结果不相同,而是它们实际匹配

考虑:

1> 1 == 1.0.
true
2> 1 =:= 1.0.
false
比较两个术语的最快方法部分取决于所涉及列表的大小,特别是取决于您是否期望断言更频繁地通过或失败

如果检查更容易失败,那么最快的检查是使用带有
=
的断言、带有
==
的等价性测试或带有
=:=
的匹配测试,而不是使用
erlang:phash2/1
。为什么?因为一旦遇到不匹配的元素,这些测试就会返回false——如果不匹配发生在列表的开头附近,那么完全可以避免对两个列表进行完全遍历

如果希望更频繁地通过检查,则类似于
erlang:phash2/1
的速度会更快,但前提是列表很长,因为每次迭代只会完全遍历一个列表(原始列表的哈希已经存储)。不过,在短列表中,简单的比较可能仍然比计算散列、存储散列、计算另一个散列然后比较散列(显然)要快。所以,和往常一样,基准

phash2版本可能如下所示:

start() ->
    A = generate_list(),
    Hash = erlang:phash2(A),
    assert_loop(Hash).

assert_loop(Hash) ->
    ok = do_stuff(),
    Hash = erlang:phash2(generate_list()),
    loop(Hash).
同样,这是一个断言循环,它将崩溃而不是干净地退出,因此需要根据您的需要进行调整


不过,基本的谜团仍然存在:在一种具有不可变变量的语言中,为什么您不知道某些东西是否会发生变化?这几乎可以肯定是程序中其他地方潜在体系结构问题的一个症状——要么就是对Erlang中不变性的误解。

如果没有更多的上下文,就有点难以理解为什么会出现这个问题,特别是因为Erlang术语是不可变的——一旦赋值,任何其他操作都不能更改变量的值,即使在同一个函数中也是如此

<> >如果你的问题是“我如何快速断言<代码>真的= a==a < /代码>?”然后考虑这个代码:

A = generate_list()
% other things in this function happen
A = A.
上面的代码片段总是断言
A
仍然是
A
,因为不可能像在Python中那样更改A

如果您的问题是“如何断言一个新列表的值生成的值与另一个已知列表的值完全相同?”则使用匹配或实际断言是最快的方法:

start() ->
    A = generate_list(),
    assert_loop(A).

assert_loop(A) ->
    ok = do_stuff(),
    A = generate_list(),
    assert_loop(A).
上面的
assert\u loop/1
函数强制断言
generate\u list/0
的输出仍然是A。不知道系统中可能发生的其他事情会影响该函数的结果,但行
A=generate\u list()如果返回的列表与
A
的值不完全相同,则
将崩溃

事实上,在本例中,无论执行多少次上述
assert\u loop/1
,都无法更改
A

现在考虑一种不同的风格:

compare_loop(A) ->
    ok = do_stuff(),
    case A =:= generate_list() of
        true  -> compare_loop(A);
        false -> terminate_gracefully()
    end.
在这里,我们为自己提供了除崩溃之外的其他选择,但效果最终是相同的,因为
=:=
不仅仅是一个相等的测试,它是一个匹配测试,意味着这两个值的计算结果不相同,而是它们实际匹配

考虑:

1> 1 == 1.0.
true
2> 1 =:= 1.0.
false
比较两个术语的最快方法部分取决于所涉及列表的大小,特别是取决于您是否期望断言更频繁地通过或失败

如果预计检查失败的频率更高,那么最快的检查是使用断言