【发布时间】:2014-11-25 08:53:00
【问题描述】:
最近开始使用 erlang 并遇到上述问题,您如何在保护语句中比较两个字符串?尝试了 string:equal(x,y) 方法,但无法让它在警卫内工作。
【问题讨论】:
标签: string erlang string-matching
最近开始使用 erlang 并遇到上述问题,您如何在保护语句中比较两个字符串?尝试了 string:equal(x,y) 方法,但无法让它在警卫内工作。
【问题讨论】:
标签: string erlang string-matching
你可以像这样使用模式匹配:
are_the_same(A, A) ->
true;
are_the_same(_, _) ->
false.
在第一个子句中,两个参数都命名为A,这将导致它们相互进行模式匹配。或者确切地说,第一个参数将使用= 运算符绑定到A 变量,然后第二个参数将使用= 运算符绑定到A 变量,但由于A 已经绑定,它会被视为“比较”。你可以阅读more about this in docs。
当然,你也可以使用如下的守卫来编写 write first clouse:
are_the_same(A, B) when A =:= B ->
【讨论】:
您不需要函数string:equal/2 来比较字符串;您可以使用运算符== 或=:=,它们在警戒测试中是允许的。例如:
foo(A, B) when A =:= B ->
equal;
foo(_, _) ->
not_equal.
尽管在大多数情况下,您希望改用模式匹配,如 other answer 中所述。
注意:从 Erlang/OTP 20.0 开始,string:equal(A, B) 不再等同于 A =:= B。 string:equal/2 现在在字素集群上运行,还有string:equal/3 and string:equal/4 在比较时可以选择忽略大小写并进行 Unicode 规范化。因此,在确定比较方法之前,您需要了解“相等”的含义。
【讨论】:
由于 Erlang 调度的性质,你可以在守卫中使用的功能是有限的;具体来说,Erlang 旨在避免守卫语句中的副作用(例如,调用另一个进程),因为守卫由调度程序评估并且不计入减少。这就是string:equal 不起作用的原因。
话虽如此,您可以使用 Erlang 的模式匹配来匹配字符串。请记住在 Erlang 中将字符串用作列表、二进制文件或 iolists(嵌套列表/二进制文件),并确保您正在测试/传递正确类型的字符串(iolists 特别难以进行模式匹配,通常是最好的使用re 模块处理,或通过iolist_to_binary 将它们转换为二进制文件。
例如,假设我们想要一个函数来测试一个字符串是否以“foo”开头:
bar("foo" ++ _Rest) -> true;
bar(<<"foo", Rest/binary>>) -> true;
bar(_Else) -> false.
如果你只是想测试一个特定的字符串,那就更简单了:
bar("foo") -> true;
bar(<<"foo">>) -> true;
bar(_Else) -> false.
【讨论】:
bar(Test ++ _Rest, Test) 和 bar(<<Test/binary, _Rest/binary>>, Test) 都不起作用)。 @legoscia 的解决方案在匹配整个变量时是最好的。如果您正在寻找部分匹配,则必须在函数声明中绑定您正在测试的变量并使用 case 语句来断言匹配。
bar(_Test = [H|TestRest], _Data = [H|DataRest]) -> bar(TestRest, DataRest); (_Test, []) -> true; bar(_Test, _Data) -> false.)