尝试计算分数并将其保持在0.2到1.5之间。 下面的代码可以工作吗?我不希望它返回,但请继续。
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),
答案 0 :(得分:9)
下面的代码可以工作吗?
不。在erlang中,您只能分配一次变量。那是您应该学的第一件事。在此语句中:
if
Score > 1.5 -> ...
已经为变量Score分配了一个值,您正在将其与小数点1.5进行比较。假设Score的值为2.0,那么特定if子句的主体将执行:
Score = 1.5;
那等于写:
2.0 = 1.5;
这将导致模式匹配错误:
- 异常错误:右侧值1.5不匹配。
在erlang中,一旦给变量赋值,此后对该变量的任何后续赋值将被视为模式匹配,即等号右侧的值将与左侧的值进行模式匹配等号。
在erlang中,通常使用多个函数子句来模式匹配不同的值:
-module(my).
-compile(export_all).
compute(Score) when Score > 1.5 ->
1.5;
compute(Score) when Score < 0.2 ->
0.2;
compute(Score) ->
Score.
在外壳中:
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
然后您可以在同一模块中定义另一个函数,如下所示:
do_stuff(Score) ->
NewScore = compute(Score),
%Do something with NewScore here...
如果您要使用if语句,我会这样做:
-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]).
为了使您的函数不超过5-6行,这将有助于将该if语句移至另一个函数。
答案 1 :(得分:4)
另一种方法是使用erlang:min/2
和erlang:max/2
来保持范围:
-module(my).
-compile(export_all).
do_stuff(Score) ->
max(min(Score, 1.5), 0.2).
如果Score
大于1.5,则min/2
将返回1.5,否则返回Score
。然后,如果该结果小于0.2,则max/2
将返回0.2,否则返回min/2
的结果。这是我们的测试功能:
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].
运行它会产生预期的结果:
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]