2010-02-11 31 views
9

Jestem nowy w firmie Erlang i próbuję zaprogramować program problemowy z ograniczonym buforem. To prawie działa, z wyjątkiem upewnienia się, że producenci nie posuną się zbyt daleko i nie zastąpią niepotrzebnych danych. Aby sobie z tym poradzić, postanowiłem spróbować umieścić strażników na mojej funkcji buffer(), tak, żebym mógł mieć wersję bez odbioru, gdy bufor jest pełny, wersja bez wysyłania, gdy bufor jest pusty, i normalna wersja do końca czasu.Nie można użyć wywołania funkcji w funkcji ochrony

Mój problem polega na tym, że ochrona dla wersji bez amplitunera wymaga ode mnie znajomości rozmiaru tablicy reprezentującej bufor, która wymaga wywołania do array:size/1. Wygląda na to, że Erlang nie zezwala na wywoływanie funkcji w strażnikach, co uniemożliwia takie działanie. Czy jest jakiś sposób obejścia tego bez zmiany deklaracji funkcji dla mojego aktora bufora?

%% buffer: array num num 
%% A process that holds the shared buffer for the producers and consumers 
buffer(Buf, NextWrite, NextRead) when NextWrite == NextRead -> 
    io:format(" * ~w, ~w, ~w~n", [array:to_list(Buf), NextRead, NextWrite]), 
    receive 
     {enqueue, Reply_Pid, Num} -> 
      io:format("~w: > ~w~n", [Reply_Pid, Num]), 
      buffer(array:set(NextWrite rem array:size(Buf), Num, Buf), NextWrite + 1, NextRead); 
     finish -> 
      io:format("finished printing~n") 
    end; 
buffer(Buf, NextWrite, NextRead) when (NextWrite - NextRead) == array:size(Buf) -> 
    io:format(" * ~w, ~w, ~w~n", [array:to_list(Buf), NextRead, NextWrite]), 
    receive 
     {dequeue, Reply_Pid} -> 
      io:format("~w: < ~w~n", [Reply_Pid, array:get(NextRead rem array:size(Buf), Buf)]), 
      Reply_Pid ! {reply, array:get(NextRead rem array:size(Buf), Buf)}, 
      buffer(Buf, NextWrite, NextRead + 1); 
     finish -> 
      io:format("finished printing~n") 
    end; 
buffer(Buf, NextWrite, NextRead) -> 
    io:format(" * ~w, ~w, ~w~n", [array:to_list(Buf), NextRead, NextWrite]), 
    receive 
     {dequeue, Reply_Pid} -> 
      io:format("~w: < ~w~n", [Reply_Pid, array:get(NextRead rem array:size(Buf), Buf)]), 
      Reply_Pid ! {reply, array:get(NextRead rem array:size(Buf), Buf)}, 
      buffer(Buf, NextWrite, NextRead + 1); 
     {enqueue, Reply_Pid, Num} -> 
      io:format("~w: > ~w~n", [Reply_Pid, Num]), 
      buffer(array:set(NextWrite rem array:size(Buf), Num, Buf), NextWrite + 1, NextRead); 
     finish -> 
      io:format("finished printing~n") 
    end. 

Odpowiedz

13

Są tylko pewne funkcje, które mogą być stosowane w strażnika, zobacz Guard Sequences in the Erlang manual. Możesz łatwo zrobić to, czego potrzebujesz:

buffer(Buf, NextWrite, NextRead) -> buffer(Buf, NextWrite, NextRead, array:size(Buf)). 

buffer(Buf, NextWrite, NextRead, _) when NextWrite == NextRead -> 
    ; 
buffer(Buf, NextWrite, NextRead, BufSize) when (NextWrite - NextRead) == BufSize -> 
    ; 
buffer(Buf, NextWrite, NextRead, _) -> 
    . 
+0

To jest ładne, proste i łatwe do zrozumienia. Dzięki. –

+0

Hi @Geoff, Czy znasz sposób na porównanie dwóch ciągów jako strażnika ?. np. - funkcja gdy string: equals (string1, string2) -> 1. –

+0

@DenisWeerasiri Jestem całkiem pewny, że 'string: equals/2' jest identyczny z' == ', więc możesz go użyć w straży . –

1

Jak wspomniał Geoff Reedy, istnieje tylko kilka BIFS, które są dozwolone w strażach.

Jednak biblioteka transformacji analiz składniowych guardian może być użyta do wywoływania dowolnej funkcji w strażnikach.

Powiązane problemy