无法在功能保护中使用函数调用

时间:2010-02-11 00:10:53

标签: erlang

我是Erlang的新手,正在尝试编写有界缓冲问题程序。它几乎可以正常工作,除了确保生产者不会过于遥远并覆盖未使用的数据。为了处理这个问题,我决定尝试在我的buffer()函数上设置保护程序,这样我就可以在缓冲区已满时使用一个没有接收的版本,在缓冲区为空时使用一个没有发送的版本,并且正常其余时间的版本。

我的问题是,无接收器版本的保护要求我知道代表缓冲区的数组的大小,这需要调用array:size/1。显然,Erlang不允许在警卫中进行函数调用,这会阻止它工作。有没有办法在不更改缓冲区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("finished printing~n")
    end.

2 个答案:

答案 0 :(得分:13)

只有某些功能可用于后卫,请参阅Guard Sequences in the Erlang manual。您可以按照以下方式轻松完成所需操作:

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

答案 1 :(得分:1)

正如Geoff Reedy所提到的那样,警卫只允许使用少量BIFS。

guardian解析变换库可用于调用守卫中的任何函数。