Raja
Raja

Reputation: 442

Erlang - If Else Condition

Trying to compute a score and maintain it between a range 0.2 to 1.5 . Will the below code work ? I don't want it to return, but continue further.

     ok = if
       Score > 1.5 ->
         Score = 1.5;
       true ->
         ok
     end,
      ok =   if
             Score < 0.2 ->
                 Score = 0.2;
             true ->
                 ok
         end,
    put(score, Score),

Upvotes: 0

Views: 1986

Answers (2)

Steve Vinoski
Steve Vinoski

Reputation: 20004

Another approach is to use erlang:min/2 and erlang:max/2 to maintain the range:

-module(my).
-compile(export_all).

do_stuff(Score) ->
    max(min(Score, 1.5), 0.2).

If Score is greater than 1.5, min/2 will return 1.5, else Score. Then, if that result is less than 0.2, max/2 will return 0.2, else the result of min/2. Here's our test function:

test_do_stuff() ->
    ScoresAndResults = [{0, 0.2},
                        {1.5, 1.5},
                        {0.2, 0.2},
                        {1.4999999, 1.4999999},
                        {1.5000001, 1.5},
                        {42, 1.5},
                        {0.19999999, 0.2},
                        {0.2000000000001, 0.2000000000001},
                        {1.2, 1.2},
                        {1, 1},
                        {-1, 0.2}],
    {Scores, Results} = lists:unzip(ScoresAndResults),
    Results = [do_stuff(Score) || Score <- Scores].

Running it produces the expected results:

1> my:test_do_stuff().
[0.2,1.5,0.2,1.4999999,1.5,1.5,0.2,0.2000000000001,1.2,1,0.2]

Upvotes: 4

7stud
7stud

Reputation: 48599

Will the below code work ?

No. In erlang, you can only assign to a variable once. That is one of the first things you should have learned. In this statement:

 if
       Score > 1.5 -> ...

the variable Score will already have been assigned a value, which you are comparing to the decimal 1.5. Suppose the value of Score is 2.0, so that the body of that particular if clause executes:

 Score = 1.5;

That is equivalent to writing:

 2.0 = 1.5;

which will result in a pattern match error:

  • exception error: no match of right hand side value 1.5.

In erlang, once you assign a value to a variable, thereafter any subsequent assignment to that variable will be treated as a pattern match, i.e. the value on the right of the equals sign will be pattern matched against the value on the left of the equals sign.


In erlang, you typically use multiple function clauses to pattern match different values:

-module(my).
-compile(export_all).

compute(Score) when Score > 1.5 ->
    1.5;
compute(Score) when Score < 0.2 ->
    0.2;
compute(Score) ->
    Score.

In the shell:

1> c(my).
my.erl:2: Warning: export_all flag enabled - all functions will be exported
{ok,my}

2> Score1 = my:compute(1.6).
1.5

3> Score2 = my:compute(1.5).
1.5

4> Score3 = my:compute(1.2).
1.2

5> Score4 = my:compute(0.1).
0.2

6> Score5 = my:compute(0.2). 
0.2

Then you can define another function in the same module like this:

do_stuff(Score) ->
    NewScore = compute(Score),
    %Do something with NewScore here...

If you want to use an if-statement, I would do it like this:

-module(my).
-compile(export_all).

do_stuff(Score) ->
    NewScore = if 
                   Score > 1.5   -> 1.5;
                   Score < 0.2   -> 0.2;
                   true          -> Score
               end,
    %Do something with NewScore here, for instance:
    io:format("~w~n", [NewScore]).

In an effort to keep your functions no longer than 5-6 lines, it would help to move that if-statement into another function.

Upvotes: 8

Related Questions