2017-04-02 43 views
2

我还是新编程和全新erlang(2周新手!)。我编辑稍微,至少它会编译和运行。但我仍然无法弄清楚将结果发送到“加工程序”以加入所有单独结果的概念。Erlang新手 - 并发和消息传递

它分裂并发送接收到的“块”来计算块。只是不知道如何让所有这些过程加入他们的个人成果。我有点理解下面的概念,但不知道这是如何实现的。我一直在尝试了很多天时间,对得到它了这一点,但不能让它没有得到错误或绑定变量做任何事情,等

-module (ccharcount1d). 
-compile(export_all). 

load(F)-> 
{ok, Bin} = file:read_file(F), 
    List=binary_to_list(Bin), 
    Ls=string:to_lower(List), 
    Length=round(length(List)/20), 
    Collect_Results = spawn(ccharcount1d, collect_results, []), 

    Sl=split(Ls,Length), 

    io:fwrite("Loaded, Split, and sent to multiple processes~n"). 




%%splits txt file into "chunks" and sends those "chunks" to be processed 
split([],_)->[]; 
split(List,Length)-> 
S1=string:substr(List,1,Length), 
case length(List) > Length of 
    true->S2=string:substr(List,Length+1,length(List)), 
    Process_Split = spawn(ccharcount1d,receive_splits,[]), 
    Process_Split ! {self(), S1}; 

    false->S2=[], 
    Process_Split = spawn(ccharcount1d,receive_splits,[]), 
    Process_Split ! {self(), S1} 

end, 

[S1]++split(S2,Length). 


%%recieves the split "chunks" and counts the results 
receive_splits()-> 
    receive 
     {From, S1} -> 
      Result=go(S1) 
      %Collect_Results ! Result 
    end. 



collect_results()-> 
    receive 
     {Process_Split, Result} -> 
      Result=join([],Result) 
    end. 



join([],[])->[]; 
join([],R)->R; 
join([H1 |T1],[H2|T2])-> 
{C,N}=H1, 
{C1,N1}=H2, 
[{C1,N+N1}]++join(T1,T2). 



count(Ch, [],N)->N; 
count(Ch, [H|T],N) -> 
    case Ch==H of 
    true-> count(Ch,T,N+1); 
    false -> count(Ch,T,N) 
end. 

go(L)-> 
Alph=[$a,$b,$c,$d,$e,$f,$g,$h,$i,$j,$k,$l,$m,$n,$o,$p,$q,$r,$s,$t,$u,$v,$w,$x,$y,$z], 
rgo(Alph,L,[]). 

rgo([H|T],L,Result)-> 
N=count(H,L,0), 
Result2=Result++[{[H],N}], 
rgo(T,L,Result2); 


rgo([],L,Result)-> Result. 
+0

*我还是新的编程和全新的erlang(2周新手!)*在我看来,糟糕的主意。学习python。花一年的时间玩它,然后决定你想从那里去哪里。 – 7stud

回答

4

再次,我新的。我正在理解这个概念。我不理解 的语法。该如何 “通过一个PID的工作进程”

start() -> 
    Work = ..., 
    JoinPid = spawn(fun() -> join_func([]) end), 
    WorkerPid = spawn(fun() -> worker_func(JoinPid, Work) end), %Pass JoinPid to worker process. 
    ... 

join_func(Acc) -> 
    receive 
     Result -> 
      join_func([Result|Acc]); %Recursive function call--the life blood of all functional languages. 

     ... 
    end 

worker_func(JoinPid, Work) -> 
    Result = ... Work ..., 
    JoinPid ! Result. %Worker process uses JoinPid to send back the results. 

而且,看看这个:

8> [$a, $b, $c]. 
"abc" 

9> "abc". 
"abc" 

输出显示[$a, $b, $c]相当于​​。这意味着你可以这样写:

[$a,$b,$c,$d,$e,$f,$g,$h,$i,$j,$k,$l,$m,$n,$o,$p,$q,$r,$s,$t,$u,$v,$w,$x,$y,$z] 

更加简洁这样的:

"abcdefghijklmnopqrstuvwxyz" 

更应如此,这样的:

11> lists:seq(97, 122). 
"abcdefghijklmnopqrstuvwxyz" 
3

你需要去的同步输出功能。 不要在函数内部产生函数,因为我看到所有结果都进入不同的过程(receive_results)。

最佳的解决方案是一个产卵过程只加载函数内部接合结果(这个过程需要自我()作为输入,以便它可以发送最终结果返回给加载功能)。然后它传递给所有参与的过程引用(J_PID)工作进程将返回结果加入进程。加入进程是receive_results类型的循环。当所有的chunks被处理时,loop终止。添加一个子句来终止join过程。在结束时,join过程会把结果发送回加载函数。

须藤代码:

J_PID =产卵加入(个体())
溢出(J_PID,....)
wait_for_result(接收结果 - > R)

+0

好的,不好意思,但是我在编程和Erlang中只有2周的时间,Theres很了解你说的我需要分解才能理解。我需要做的是如果我的理解正确,我需要删除它: DELETE'rgo([],L,Result) - >' DELTETE'Process_Results = spawn(ccharcount1d,receive_results,[]) ,' DELETE'Process_Results! {self(),Result} .' 简单地放在'rgo([],L,Result) - > Result.' – chitown88

+0

然后在加载函数中,'io:format(“Load,split ... ...),'我可以派生加入过程。 – chitown88

+0

你有点迷失了我。我明白你的意思是说结果会落在不同的过程中。但我不完全理解“通过加入进程到工作进程部分” – chitown88