This program is crashing despite seeming to work. I don't understand why though. I'm trying to accomplish a deep merge and need conditional logic.
Given the following list:
ManOne = #{ "Bob" => #{"Sagget" => #{}} }
ManTwo = #{ "Bob" => #{"Daniels" => #{}} }
I'm trying to compare them as follows, this function returns true as expected:
check_if_same(M1, M2) ->
{ok, lists:sort( maps:keys(M1) ) == lists:sort( maps:keys(M2) )}.
merger(M1, M2) ->
M1_Keys = maps:keys(M1),
M2_Keys = maps:keys(M2),
do_merge(M1, M2, M1_Keys).
do_merge(M1, M2, [Head|Tail]) ->
Check = check_if_same(M1, M2),
io:fwrite("Check is: ~p\n", [Check]),
case Check of
{ok, true} ->
io:fwrite("true\n");
{ok, false} ->
io:fwrite("false\n")
end,
do_merge(M1, M2, Tail);
do_merge(M1, M2, []) ->
ok.
check_if_same(M1, M2) ->
{ok, lists:sort( maps:keys(M1) ) == lists:sort( maps:keys(M2) )}.
gives the following output:
Check is: {ok,true}
true
{"init terminating in do_boot",{{badmap,ok},[{maps,keys,[ok],[]},{helloworld,merger,2,[{file,"helloworld.erl"},{line,9}]},{init,start_em,1,[]},{init,do_boot,3,[]}]}}
init terminating in do_boot ()
Crash dump is being written to: erl_crash.dump...done
2条答案
按热度按时间ezykj2lf1#
Let's go over your question first because there's a few misconceptions and/or corrections that we can make.
Your Description
This program is crashing despite seeming to work. I don't understand why though. I'm trying to accomplish a deep merge and need conditional logic.
Given the following list:
Note that the above are NOT lists, they are maps, which function entirely differently.
A map is, for all intents and purposes, a lookup table until it contains ~31 key/value pairs.
At this point, it becomes a HashMap (this can be seen by viewing the elements as they become unordered after the map becomes a HashMap).
I'm trying to compare them as follows, this function returns true as expected:
This is an incorrect way to assert equality; in erlang, it is suggested to not use
==
to check equality.Instead,
=:=
should be used.The reason for this is due to the fact that
==
does NOT check the type of the elements it is comparing and only takes a fuzzy value - i.e1 == 1.0
will return true but1 =:= 1.0
will return false.Personally, I would recommend instead using Erlang's Pattern-Matching to check your values.
This could be implemented using the following snippet:
Note that in the above snippet, I only ever returned
true
orfalse
- my recommendation for cleaner code would be to keep to the following formats;ok
- This is typically for functions where you care about the effect and not the returntrue
|false
- This is typically for comparison functions, i.eis_binary/1
,is_function/1
{ok, Value}
- This would typically be for any function where you care about the value returned{error, Reason}
- This would be used whenever you expect an error so that you can bubble the error back up the chain with an easy-to-match formatYour Code Snippet
Now, the above snippet (other than being a bit inefficient) is perfectly okay erlang and will work as expected
gives the following output:
This crash dump is where the real issue is;
From this we can tell that we
io:fwrite("Check is: ~p\n", [Check])
){ok, true}
path in the case (io:fwrite("true\n")
)The next line is where we see the actual problem, let's break it down:
"init terminating in do_boot"
- We failed when starting up, this might be when running an escript or starting an appNow let's break down that tuple:
What we can take away from this is that you're calling merger in your code with an invalid value of
ok
on line 9 of helloworld.erlpiwo6bdm2#
这里有一些遗漏的信息。虽然这段代码看起来像是第一个草稿或步骤,但它的工作方式和预期的一样。我在shell中测试了它,得到了以下代码:
其给出:
也许您还可以告诉我们合并
ManOne
和ManTwo
的预期结果是什么