Erlang case statement

14,361

Solution 1

In the format you use ~p. It means -- print value. So you must specify what value to print.

last line of case must be

_ -> io:format("no match ~p~n",[P])

Besides, io:format returms 'ok'. So if P is not x y or z, your function will return 'ok' instead of numeric value. I would suggest to return tagged value to separate correct and error returns. Kind of

fall_velocity(P, D) when D >= 0 ->
case P of
x -> {ok,math:sqrt(2 * 9.8 * D)};
y -> {ok,math:sqrt(2 * 1.6 * D)};
z -> {ok,math:sqrt(2 * 3.71 * D)};
Otherwise-> io:format("no match:~p~n",[Otherwise]),
            {error, "coordinate is not x y or z"}
end.

Solution 2

To make the comments to the other answer explicit, this is how I would write that function:

-module(crop).
-export([fall_velocity/2]).

fall_velocity(P, D) when D >= 0 ->
    case P of
        x -> math:sqrt(2 * 9.8 * D);
        y -> math:sqrt(2 * 1.6 * D);
        z -> math:sqrt(2 * 3.71 * D)
    end.

That is, don't handle the incorrect argument in your case expression. If someone passes foo as an argument, you'll get the error {case_clause, foo} along with a stacktrace that points to this function and its caller. This also means that this function cannot leak incorrect values into the rest of the code as a result of being called with incorrect arguments.

Returning {ok, Result} | {error, Error} as in the other answer is equally valid. You'll need to choose the variant that fits your case best.

Share:
14,361
Tharanga Abeyseela
Author by

Tharanga Abeyseela

Open-source lover, more focus on infrastructure automation,Cloud,DevOps,Programming in Python,Shell scripts.

Updated on June 04, 2022

Comments

  • Tharanga Abeyseela
    Tharanga Abeyseela almost 2 years

    I have the following Erlang code and it is giving the warning as follows, when i try to compile it, but that make sense. function need two arguments, but i need to patten match "everything else" rather x, y or z.

    -module(crop).
    -export([fall_velocity/2]).
    
    fall_velocity(P, D) when D >= 0 ->
    case P of
    x -> math:sqrt(2 * 9.8 * D);
    y -> math:sqrt(2 * 1.6 * D);
    z -> math:sqrt(2 * 3.71 * D);
    (_)-> io:format("no match:~p~n")
    end.
    
    crop.erl:9: Warning: wrong number of arguments in format call. 
    

    I was trying an anonymous variable after io:format, but still it is not happy.

  • Berzemus
    Berzemus over 10 years
    I'd throw an exception, or maybe just don't even check for anything else than x,y,z. Erlang fails comprehensibly, no need to overdo it.
  • Odobenus Rosmarus
    Odobenus Rosmarus over 10 years
    right. But if do not check, you can get an error somewhere much later than invoking function. {ok,R} = fall_velocity(A,B) could point an error earlier.
  • Berzemus
    Berzemus over 10 years
    In fact, it depends on who calls the function. If the function is part of an API, tagged values are indeed welcome. But if the function is an internal part deep inside your codebase, you end up having case statements everywhere, continuously error-checking your own code, which is a needless hassle. Just let it fail.
  • rvirding
    rvirding over 10 years
    It is one of those things which are easy to check so "they" decided to add a warning check for it. It is only a warning so if you decide to ignore then you will get an error when you run the code.