Reputation: 442
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
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
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