这是我在阅读Joe的Erlang书时找到的代码。但我无法理解。
odds_and_evens_acc(L) ->
odds_and_evens_acc(L, [], []).
odds_and_evens_acc([H|T], Odds, Evens) ->
case (H rem 2) of
1 -> odds_and_evens_acc(T, [H|Odds], Evens);
0 -> odds_and_evens_acc(T, Odds, [H|Evens])
end;
odds_and_evens_acc([], Odds, Evens) ->
{Odds, Evens}.
请帮我解决这个问题。
答案 0 :(得分:4)
%% There are two functions - odds_and_evens_acc/1 and odds_and_evens_acc/3
%% First function. It takes a list of integers and splits it on two lists -
%% odds and evens.
%% The function calls odds_and_evens_acc/3 with three arguments -
%% given List of integers and two empty lists which are
%% accumulators for odds and evens. Actually they are just initial values
%% for lists, where we store odds and evens.
odds_and_evens_acc(L) ->
odds_and_evens_acc(L, [], []).
%% Second function. It takes 3 arguments - list of integers and initial lists for
%% storing odds and evens. The functions works recursively. On each step it
%% takes first element of list, test if it is odd or even, add that elemnt
%% to appropriate list. Then function calls itself
%% with tail (first element deleted) of the list and lists of o/e
%% (one with one new element, another is the same as it was passed).
%% When the list is empty function finishes.
%%
%% Function has two clauses.
%% First clause - the list is not empty - so we should proceed.
%% Function splits it on first element (head)
%% and reminder (tail) with pattern matching ([H|T]).
odds_and_evens_acc([H|T], Odds, Evens) ->
%% Test head if it is odd or even.
%% In both cases the function call itself again with the tail of the list and
%% accumulators (note: head is added in appropriate accumulator).
case (H rem 2) of
1 -> odds_and_evens_acc(T, [H|Odds], Evens);
0 -> odds_and_evens_acc(T, Odds, [H|Evens])
end;
%% Second clause. The list is empty.
%% Function finishes returning tuple with two accumulators
%% which are two lists, the first
%% contains all odd elemnts of the initial list and the second - all evens.
odds_and_evens_acc([], Odds, Evens) ->
{Odds, Evens}.
答案 1 :(得分:2)
当您尝试理解某些代码时,您可以使用调试器 - 尤其是使用非常小的代码。
编写一个名为test1.erl的文件:
-module (test1).
-compile(export_all).
odds_and_evens_acc(L) ->
odds_and_evens_acc(L, [], []).
odds_and_evens_acc([H|T], Odds, Evens) ->
case (H rem 2) of
1 -> odds_and_evens_acc(T, [H|Odds], Evens);
0 -> odds_and_evens_acc(T, Odds, [H|Evens])
end;
odds_and_evens_acc([], Odds, Evens) ->
{Odds, Evens}.
在同一目录下启动erlang shell:erl或werl。
1> %% compile the code for debug
1> c(test1,[debug_info]).
{ok,test1}
2> %% create a list of integer for test
2> L=lists:seq(1,8).
[1,2,3,4,5,6,7,8]
3> %% start the debugger
3> debugger:start().
{ok,<0.38.0>}
4> %% in the menu Module, select interpret... and then the file test1.erl
4> %% then check the box Auto attach on break
4> %% double click on module name test1
4> %% put a break point on the first line of code
4> %% start the function
4> test1:odds_and_evens_acc(L).
你应该到达这个窗口:
然后您可以使用步骤按钮并查看值面板以查看程序的演变。通过打开跟踪面板可以看到执行跟踪:选项/跟踪窗口/跟踪区域