Erlang: no match of right hand side value

2020-03-26 06:12发布

问题:

A common error message in Erlang programs is the following:

** exception error: no match of right hand side value 'foo'
     in function module:function/2 (file.erl, line 42)

How can I debug this?

回答1:

Here is how to debug this kind of error:

  1. Go to module:function/2 (file.erl, line 42)

  2. Find the offending matching operation that is definitely there

  3. Replace the left-hand side with a fresh variable. Here you may figure out that you are trying to pattern-match against an already bound variable...

  4. Add a call to erlang:display/1 with the new variable

  5. Run the program again to print the value of this variable and understand why it doesn't match the given pattern

Here are some examples:

  • Example 1:

    {_, Input} = io:get_line("Do you want to chat?") % Line 42
    

    Replace this with:

    Fresh1 = io:get_line("Do you want to chat?"),
    erlang:display(Fresh1),
    {_, Input} = Fresh1
    

    Run the program again:

    1> module:run().
    Do you want to chat? Yes
    "Yes\n"
    ** exception error: no match of right hand side value "Yes\n"
      in function module:function/2 (file.erl, line 44)
    

    You can see that io:get_line/1 returns a string and not a tuple, so the matching against {_, Input} fails.

  • Example 2:

    In an Erlang shell:

    2> Pid = echo:start().
    ** exception error: no match of right hand side value <0.41.0>
    

    Here the variable Pid is definitely already bound to another value...

    3> Pid.
    <0.39.0>
    

    You can make the shell forget such a binding with f(Var) or f():

    4> f(Pid).
    ok
    5> Pid.
    * 1: variable 'Pid' is unbound
    6> Pid = echo:start().
    <0.49.0>
    


回答2:

the error report is more friendly that the simple bad match, it gives also the value that fails to match. If this value is "small" enough, it is fully displayed and it is often enough to understand what is going wrong:

-module(err).

-export([test/0]).

test() ->
    "ok\n" = io:get_line("an input ? ").

test2() ->
    F = fun() ->
        "ok\n" = io:get_line("an input ? ")
    end,
    F().

in the shell:

1> c(err).
{ok,err}
2> err:test().
an input ? ok
"ok\n"
3> err:test().
an input ? ko
** exception error: no match of right hand side value "ko\n"
     in function  err:test/0 (err.erl, line 6)
4> F = fun() -> a = 10 end.
#Fun<erl_eval.20.106461118>
5> F().
** exception error: no match of right hand side value 10
6> err:test2().
an input ? ok
"ok\n"
7> err:test2().
an input ? ko
** exception error: no match of right hand side value "ko\n"
     in function  err:'-test2/0-fun-0-'/0 (err.erl, line 10)
8>