Erlang 无法在函数保护中使用函数调用

Erlang 无法在函数保护中使用函数调用,erlang,Erlang,我是Erlang新手,正在尝试编写一个有界缓冲区问题程序。除了确保制作人不会走得太远,覆盖未使用的数据外,它几乎可以正常工作。为了处理这个问题,我决定尝试在buffer()函数上设置防护,这样当缓冲区已满时可以使用w/o receive版本,当缓冲区为空时可以使用w/o send版本,其余时间可以使用普通版本 我的问题是,无接收器版本的保护要求我知道表示缓冲区的数组的大小,这需要调用array:size/1。显然,Erlang不允许在guards中调用函数,这会阻止它工作。有什么方法可以解决这个

我是Erlang新手,正在尝试编写一个有界缓冲区问题程序。除了确保制作人不会走得太远,覆盖未使用的数据外,它几乎可以正常工作。为了处理这个问题,我决定尝试在buffer()函数上设置防护,这样当缓冲区已满时可以使用w/o receive版本,当缓冲区为空时可以使用w/o send版本,其余时间可以使用普通版本

我的问题是,无接收器版本的保护要求我知道表示缓冲区的数组的大小,这需要调用
array:size/1
。显然,Erlang不允许在guards中调用函数,这会阻止它工作。有什么方法可以解决这个问题而不改变我的缓冲区参与者的函数声明吗

%% 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.
%%缓冲区:数组num
%%为生产者和消费者保存共享缓冲区的进程
当NextWrite==nextrade->
io:format(“*~w,~w,~w~n”,[array:to_list(Buf),NextRead,NextWrite]),
接收
{enqueue,Reply_Pid,Num}->
io:格式(“~w:>~w~n”,[Reply\u Pid,Num]),
缓冲区(数组:set(NextWrite rem数组:size(Buf)、Num、Buf)、NextWrite+1、nextrade);
完成->
io:格式(“已完成打印~n”)
结束;
缓冲区(Buf,NextWrite,NEXTTREAD)何时(NextWrite-NEXTTREAD)=数组:大小(Buf)->
io:format(“*~w,~w,~w~n”,[array:to_list(Buf),NextRead,NextWrite]),
接收
{退出队列,回复}->
io:format(“~w:<~w~n”,[Reply\u Pid,array:get(nextrade-rem array:size(Buf),Buf)],
答复!!{reply,array:get(nextrade-rem-array:size(Buf),Buf)},
缓冲区(Buf、NextWrite、NextRead+1);
完成->
io:格式(“已完成打印~n”)
结束;
缓冲区(Buf、NextWrite、NextRead)->
io:format(“*~w,~w,~w~n”,[array:to_list(Buf),NextRead,NextWrite]),
接收
{退出队列,回复}->
io:format(“~w:<~w~n”,[Reply\u Pid,array:get(nextrade-rem array:size(Buf),Buf)],
答复!!{reply,array:get(nextrade-rem-array:size(Buf),Buf)},
缓冲区(Buf、NextWrite、NextRead+1);
{enqueue,Reply_Pid,Num}->
io:格式(“~w:>~w~n”,[Reply\u Pid,Num]),
缓冲区(数组:set(NextWrite rem数组:size(Buf)、Num、Buf)、NextWrite+1、nextrade);
完成->
io:格式(“已完成打印~n”)
结束。

防护装置中只能使用某些功能,请参阅。您可以按以下方式轻松完成所需的工作:

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

正如Geoff Reedy所提到的,守卫中只允许少数BIF


但是解析转换库可以用来调用guards中的任何函数。

这很好,很简单,也很容易理解。谢谢。嗨@Geoff,你知道一种比较两个字符串作为守卫的方法吗?。例如-string:equals(string1,string2)->1时的函数。@Denisweerairi我很确定
string:equals/2
=
完全相同,所以您可以在防护中使用它。