如何在Erlang中为字符串变量重新赋值?

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

我是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",

我得到同样的错误。
我会很感激你的帮助。

bxjv4tth

bxjv4tth1#

You can't. Erlang has a feature called "single assignment", meaning that you can't change the value of a variable after assigning it for the first time. If you try to do that, it becomes a pattern match instead, and you get a badmatch error just like if you try to do "test1" = "test2" .
Your example can be written as:

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

See this question and its answers for more about single assignment.
In your expanded example, what you're trying to do can be achieved with a fold. That is, given a list and an additional value called an "accumulator", go through the list and call a function for each element, and let the return value of that function be the new accumulator - and return the accumulator in the end.
Use lists:foldl/3 for that, like this:

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).
fslejnso

fslejnso2#

= is not an assignment operator in erlang, rather it's a pattern match operator.
If you write:

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

and A has not been bound to (or you can say assigned) a value yet, then erlang attempts to create a match for the right hand side (because = is the match operator). To create a match for the right hand side, erlang binds/assigns A the value 10 (for fun you can assume that *&* is the assignment operator in erlang, so erlang does A *&* 10 to assign 10 to the variable A).
It works the same way if you write:

B = 10,

In order for erlang to create a match for the right hand side, erlang assigns B the value 10 : B *&* 10 , and the match succeeds, so execution continues on the next line. However, if you write:

C = 3,
C = 22,

then in the first line, erlang assigns the value 3 to C : C *&* 3 to find a match for the right hand side (because = is the match operator). But the second line is equivalent to:

3 = 22,

And the error message will say that the match operator = failed because there is no possible way to make the left hand side match the right hand side 22 .

xghobddn

xghobddn3#

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().

由于X是匿名函数参数的名称,因此该程序打印XY而不是X

相关问题