【问题标题】:How to reassign value to string variables in Erlang?如何在 Erlang 中为字符串变量重新赋值?
【发布时间】:2019-02-06 15:00:46
【问题描述】:

我是 Erlang 的新手。我只想为字符串变量重新赋值:

get_alert_body(Packet) ->
    BodyElement = element(8,Packet),
    Body = "my text",
    Els = xmpp:get_els(Packet),
    lists:foreach(fun(El) ->
        ElementName = io_lib:format("~s",[xmpp:get_name(El)]),
        IsFile = string:equal(ElementName,"fileType"),
        if
            IsFile ->
                FileType = fxml:get_tag_cdata(El),
                IsPhoto = string:equal(FileType,"photo"),
                IsVideo = string:equal(FileType,"video"),
                if
                    IsPhoto ->
                        %% if it gets to this I would like to return "my photo"
                        Body = "my photo";
                    IsVideo ->
                        %% else if it gets to this I would like to return "my video"
                        Body = "my video";
                    true ->
                        %% otherwise I would like to return "my text"
                        ok
                end;
            true ->
                ok
        end
    end, Els),
    Body.

但我收到此错误:

error,{badmatch,"test2"}

即使我做了类似的事情:

A = "test1",
A = "test2",

我得到同样的错误。

感谢您的帮助。

【问题讨论】:

    标签: string erlang


    【解决方案1】:

    你不能。 Erlang 有一个叫做“单一赋值”的特性,这意味着你不能在第一次赋值后改变一个变量的值。如果您尝试这样做,它会变成模式匹配,并且您会收到 badmatch 错误,就像您尝试执行 "test1" = "test2" 一样。

    你的例子可以写成:

    A =
      if
          Condition ->
              "test2";
          true ->
              "test1"
      end
    

    请参阅this question 及其答案,了解有关单一作业的更多信息。


    在您的扩展示例中,您尝试做的事情可以通过折叠来实现。也就是说,给定一个列表和一个称为“累加器”的附加值,遍历列表并为每个元素调用一个函数,并让该函数的返回值成为新的累加器 - 最后返回累加器。

    为此使用lists:foldl/3,如下所示:

    get_alert_body(Packet) ->
        BodyElement = element(8,Packet),
        DefaultBody = "my text",
        Els = xmpp:get_els(Packet),
        lists:foldl(fun(El, Body) ->
            ElementName = io_lib:format("~s",[xmpp:get_name(El)]),
            IsFile = string:equal(ElementName,"fileType"),
            if
                IsFile ->
                    FileType = fxml:get_tag_cdata(El),
                    IsPhoto = string:equal(FileType,"photo"),
                    IsVideo = string:equal(FileType,"video"),
                    if
                        IsPhoto ->
                            %% if it gets to this I would like to return "my photo"
                            "my photo";
                        IsVideo ->
                            %% else if it gets to this I would like to return "my video"
                            "my video";
                        true ->
                            %% otherwise return the existing value
                            Body
                    end;
                true ->
                    ok
            end
        end, DefaultBody, Els).
    

    【讨论】:

    • 非常感谢。我将编辑我的示例代码。因为我很困惑如何将它与循环一起使用。
    • 非常感谢。我最终使用了不同的解决方案,但您的回复对我帮助很大。
    【解决方案2】:

    = 不是 erlang 中的赋值运算符,而是 模式匹配 运算符。

    如果你写:

    {A, hello} = {10, hello}.
    

    A 还没有绑定到(或者你可以说分配)一个值,然后erlang尝试为右侧创建一个匹配项(因为= 是匹配运算符)。为了为右侧创建匹配,erlang 绑定/分配 A 值 10(为了好玩,您可以假设 *&* 是 erlang 中的赋值运算符,因此 erlang 使用 A *&* 10 将 10 分配给变量 A)。

    如果你写,它的工作方式是一样的:

    B = 10,
    

    为了让erlang为右边创建匹配,erlang将B赋值为10:B *&* 10,匹配成功,所以下一行继续执行。但是,如果你写:

    C = 3,
    C = 22,
    

    然后在第一行中,erlang 将值3 分配给CC *&* 3 以找到右侧的匹配项(因为= 是匹配运算符)。但第二行相当于:

    3 = 22,
    

    并且错误消息会说匹配运算符=失败,因为没有办法让左侧匹配右侧22

    【讨论】:

      【解决方案3】:

      Erlang 中的变量不能重新赋值,但是可以"shadowed" 来达到类似的效果。在此示例中,变量 X 在匿名函数范围内被“重新定义”为 X ++ Y

      -module(main).
      -export([main/1]).
      
      main([_]) ->
          X = "X",
          Y = "Y",
          fun(X) -> io:fwrite(X) end(X++Y),
          init:stop().
      

      此程序打印XY 而不是X,因为X 是匿名函数参数的名称。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-09-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-03-13
        • 1970-01-01
        • 1970-01-01
        • 2017-01-02
        相关资源
        最近更新 更多