Erlang:在guard语句中匹配字符串

8nuwlpux  于 2022-12-08  发布在  Erlang
关注(0)|答案(3)|浏览(164)

最近才开始使用Erlang,遇到了上面的问题,如何在guard语句中比较两个字符串呢?尝试了string:equal(x,y)方法,但无法在guard语句中使用。

cedebl8k

cedebl8k1#

您可以像这样使用模式匹配:

are_the_same(A, A) ->
  true;
are_the_same(_, _) ->
  false.

在第一个子句中,两个参数都命名为A,这将导致它们相互进行模式匹配。或者确切地说,第一个参数将使用=运算符绑定到A变量,而第二个参数将使用=运算符绑定到A变量。但是由于A已经被绑定,它将被视为“比较”。你可以在文档中阅读更多关于这方面的信息。
当然,您也可以使用如下形式的guard来编写write first clouse:

are_the_same(A, B) when A =:= B ->
omhiaaxx

omhiaaxx2#

You don't need the function string:equal/2 to compare strings; you can use the operators == or =:= , which are allowed in guard tests. For example:

foo(A, B) when A =:= B ->
    equal;
foo(_, _) ->
    not_equal.

Though in most cases you'd want to use pattern matching instead, as described in the other answer .
NB: As of Erlang/OTP 20.0, string:equal(A, B) is no longer equivalent to A =:= B . string:equal/2 now operates on grapheme clusters, and there are also string:equal/3 and string:equal/4 that can optionally ignore case when comparing and do Unicode normalisation. So you need to understand what you mean by "equal" before settling on a comparison method.

vqlkdk9b

vqlkdk9b3#

The functions you can use in guards are limited because of the nature of Erlang's scheduling; specifically, Erlang aims to avoid side-effects in guard statements (e.g., calling to another process) because guards are evaluated by the scheduler and do not count against reductions. This is why string:equal does not work.
That being said, you can use Erlang's pattern matching to match strings. Please bear in mind the use of strings as lists, binaries, or iolists (nested lists/binaries) in Erlang, and make sure you're testing/passing strings of the right type (iolists are particularly hard to pattern match and are usually best handled with the re module, or converting them to binaries via iolist_to_binary ).
For example, say we want a function that tests to see if a string begins with "foo":

bar("foo" ++ _Rest) -> true;
bar(<<"foo", Rest/binary>>) -> true;
bar(_Else) -> false.

If you just want to test for a particular string, it's even easier:

bar("foo") -> true;
bar(<<"foo">>) -> true;
bar(_Else) -> false.

相关问题