【问题标题】:Erlang: Matching strings in guard statementErlang:匹配保护语句中的字符串
【发布时间】:2014-11-25 08:53:00
【问题描述】:

最近开始使用 erlang 并遇到上述问题,您如何在保护语句中比较两个字符串?尝试了 string:equal(x,y) 方法,但无法让它在警卫内工作。

【问题讨论】:

    标签: string erlang string-matching


    【解决方案1】:

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

    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 ->
    

    【讨论】:

    • 使用模式匹配是在 erlang 中做任何事情的最有效方式。这在构建复杂软件时变得非常重要。
    【解决方案2】:

    您不需要函数string:equal/2 来比较字符串;您可以使用运算符===:=,它们在警戒测试中是允许的。例如:

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

    尽管在大多数情况下,您希望改用模式匹配,如 other answer 中所述。


    注意:从 Erlang/OTP 20.0 开始,string:equal(A, B) 不再等同于 A =:= Bstring:equal/2 现在在字素集群上运行,还有string:equal/3 and string:equal/4 在比较时可以选择忽略大小写并进行 Unicode 规范化。因此,在确定比较方法之前,您需要了解“相等”的含义。

    【讨论】:

      【解决方案3】:

      由于 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.
      

      【讨论】:

      • @legoscia answers 解决了它,但如果你不介意:你将如何使用这种方法将一个变量与另一个变量进行模式匹配? > 表达式究竟是做什么的?
      • 不幸的是,模式匹配的限制之一正是您所描述的:您无法将另一个变量与列表或二进制文件匹配(例如,bar(Test ++ _Rest, Test)bar(&lt;&lt;Test/binary, _Rest/binary&gt;&gt;, Test) 都不起作用)。 @legoscia 的解决方案在匹配整个变量时是最好的。如果您正在寻找部分匹配,则必须在函数声明中绑定您正在测试的变量并使用 case 语句来断言匹配。
      • 和 >,除非我弄错了,匹配一个两字节的二进制文件。
      • 啊,好吧。所以匹配变量: '=:=' 并使用您上面描述的进行部分匹配?
      • 确实如此。如果部分匹配不能像我描述的那样工作,你总是可以遍历列表的元素或二进制的字节(bar(_Test = [H|TestRest], _Data = [H|DataRest]) -&gt; bar(TestRest, DataRest); (_Test, []) -&gt; true; bar(_Test, _Data) -&gt; false.
      猜你喜欢
      • 2018-10-02
      • 2011-02-23
      • 1970-01-01
      • 1970-01-01
      • 2018-10-06
      • 2018-09-29
      • 1970-01-01
      • 2019-12-24
      • 1970-01-01
      相关资源
      最近更新 更多