开发者

Unable to use function call in function guard

开发者 https://www.devze.com 2022-12-20 00:37 出处:网络
I\'m new to Erlang and am trying to program a bounded-buffer problem program.It is almost working, except for making sure the producers don\'t get too far ahead and overwrite unconsumed data.To handle

I'm new to Erlang and am trying to program a bounded-buffer problem program. It is almost working, except for making sure the producers don't get too far ahead and overwrite unconsumed data. To handle this, I decided to try putting guards on my buffer() function so that I could have a version w/o receive used when the buffer is full, a version w/o send used when the buffer is empty, and a normal version for the rest of the time.

My problem is that the guard for the receiver-less version requires me to know the size of the array representing the buffer, which requires a call to array:size/1. Apparently, Erlang does not allow function invocations in guards, which prevents this from working. Is there some way to work around this without changing the function declaration for my buffer actor?

%% 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(开发者_StackOverflow中文版"finished printing~n")
    end.


There are only certain functions that can be used in a guard, see Guard Sequences in the Erlang manual. You can easily do what you need as follows:

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, _) ->
  .


As Geoff Reedy has mentioned there are only few BIFS that are allowed in guards.

But the guardian parse transform library can be used to call any function in guards.

0

精彩评论

暂无评论...
验证码 换一张
取 消