2017-04-02 3 views
2

Je suis encore nouveau à la programmation et tout nouveau erlang (2 semaines newbie!). J'ai édité légèrement afin qu'au moins il compile et fonctionne. Mais je ne peux toujours pas comprendre le concept d'envoyer les résultats à un "processus de menuisier" pour joindre tous les résultats séparés.Erlang newbie - la concurrence et le passage de message

Il se scinde et envoie les "morceaux" reçus pour compter les morceaux. Je ne sais pas comment obtenir tous ces processus pour rejoindre leurs résultats individuels. Je comprends en quelque sorte le concept ci-dessous, mais je n'ai aucune idée de comment cela est implanté. J'ai essayé pendant plusieurs jours et heures pour l'obtenir à ce point, mais ne peut pas l'obtenir à rien faire sans obtenir des erreurs ou des variables non liées, etc.

-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

* Je suis encore nouveau à la programmation et nouveau erlang (2 semaines newbie!) * idée terrible à mon avis. Apprenez python. Passez une année à vous amuser avec, puis décidez où vous voulez aller à partir de là. – 7stud

Répondre

4

, i suis nouveau. Je comprends le concept. Je ne comprends pas la syntaxe. la façon de "passer un pid à un processus de travail"

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. 

Aussi, consultez ceci:

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

9> "abc". 
"abc" 

La sortie montre que [$a, $b, $c] est équivalente à "abc". Cela signifie que vous pouvez écrire ceci:

[$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] 

beaucoup plus succinctement comme ceci:

"abcdefghijklmnopqrstuvwxyz" 

et plus encore, comme ceci:

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

Vous devez synchroniser la sortie de go fonction. Ne pas lancer la fonction à l'intérieur, car je vois que tous les résultats vont à un processus différent (receive_results).

Les meilleures solutions génèrent un processus de jonction de résultat à l'intérieur de la fonction de chargement (ce processus prend self() comme entrée pour renvoyer le résultat final à la fonction de chargement). Transférer ensuite cette référence de processus à tous Processus de travail qui renvoie le résultat à join process.Join processus est boucle de type de receive_results.Loop se termine lorsque tous les morceaux sont traités.Ajoutez une clause pour terminer le processus de jointure. Lorsque le processus de jointure est terminé, le résultat renvoie la fonction load.

Code Sudo:

J_PID = spawn join (auto())
déversée (J_PID, ....)
wait_for_result (résultat de la réception -> R) à nouveau

+0

Ok, désolé mais je suis seulement 2 semaines dans la programmation et Erlang, Theres beaucoup dans ce que vous avez dit que je dois décomposer pour comprendre. Si je comprends bien, j'ai besoin de supprimer ceci: SUPPRIMER 'rgo ([], L, Résultat) ->' DELTETE 'Process_Results = spawn (ccharcount1d, receive_results, []) , ' SUPPRIMER' Process_Results! {self(), Result} .' Mettre en place simplement 'rgo ([], L, Résultat) -> Résultat .' – chitown88

+0

puis dans la fonction load, après' io: format ("Load, split ... ...), 'Je pourrais générer le processus de jointure. – chitown88

+0

vous m'avez perdu. Je vois ce que vous voulez dire que les résultats sont ensuite dirigés vers différents processus. mais je ne comprends pas très bien "le processus de jointure de passe à la partie de processus de travail" – chitown88