所以我对 Erlang 非常感兴趣。我找不到借口将它用于任何大事,但我不时尝试将其用于玩具问题。
现在,我正在实现一个罗马数字翻译器。我现在只是在做“到”部分,我发现代码非常重复。它就像一个魅力,但是,好吧,看看它:
-module(roman).
-compile([export_all]).
toRoman(N) ->
toRoman(N, []).
toRoman(0,Acc) ->
lists:reverse(lists:flatten(Acc));
toRoman(N, Acc) when N >= 1000 ->
toRoman(N-1000,["M"|Acc]);
toRoman(N,Acc) when N >= 900 ->
toRoman(N-900,["CM" | Acc]);
toRoman(N,Acc) when N >= 500 ->
toRoman(N-500,["D" | Acc]);
toRoman(N,Acc) when N >= 400 ->
toRoman(N-400, ["CD" | Acc]);
toRoman(N,Acc) when N >= 100 ->
toRoman(N-100, ["C" | Acc]);
toRoman(N,Acc) when N >= 90 ->
toRoman(N-90, ["XC" | Acc]);
toRoman(N,Acc) when N >= 50 ->
toRoman(N-50, ["L" | Acc]);
toRoman(N, Acc) when N >= 40 ->
toRoman(N-40, ["XL" | Acc]);
toRoman(N, Acc) when N >= 10 ->
toRoman(N-10, ["X" | Acc]);
toRoman(N, Acc) when N >= 9 ->
toRoman(N-9, ["IX" | Acc]);
toRoman(N, Acc) when N >= 5 ->
toRoman(N-5, ["V" | Acc]);
toRoman(N, Acc) when N >= 4 ->
toRoman(N-4, ["IV" | Acc]);
toRoman(N, Acc) ->
toRoman(N-1, ["I" | Acc]).
test() ->
Test = fun(X) -> io:format("~p -> ~p~n", [X, toRoman(X)]) end,
lists:map(Test, [0,1,3,6,23,43,75,87,13,23, 3999, 3998, 2531, 140]).
我觉得有更好的方法可以做到这一点。任何人都可以提供一些见解吗?
最佳答案
其实你的代码不是那么重复。它只是看起来像,因为文本形成了重复的模式。但是你的每个子句都处理一个特定的情况,它们之间几乎没有逻辑重叠。您可以在 switch 语句中重新实现,但会得到类似的重复。罗马数字翻译中的情况太多了,我认为您无法避免使每个单独的决定造成重复的感觉。
关于syntax - 帮我改进这个Erlang?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1678465/