我在考虑函数调用时隐藏状态。 例如:
body_to_client(Req, ClientRef) ->
case cowboy_req:body(Req) of
{ok, Data, Req2} ->
ok = hackney:send_body(ClientRef, Data),
Req2;
{more, Data, Req2} ->
ok = hackney:send_body(ClientRef, Data),
body_to_client(Req2, ClientRef)
end.
但我想将这些代码分成几个部分并隐藏实现:
body_to_client(ReadRequestBody, ClientRef) ->
case ReadRequestBody() of
{ok, Data} ->
ok = hackney:send_body(ClientRef, Data),
ReadRequestBody;
{more, Data} ->
ok = hackney:send_body(ClientRef, Data),
body_to_client(ReadRequestBody, ClientRef)
end.
其中ReadRequestBody是包含所有细节和状态的函数。 我认为它应该是这样的:
ReadRequestBody = fun() ->
{Status, Data, Req2} = cowboy_req:body(Req),
{Status, Data}
end
但我不知道如何处理Req2并在下次通话中传递它。
答案 0 :(得分:4)
提取Req2的唯一方法是使用ReadRequestBody
的其余结果返回它:
ReadRequestBody = fun() ->
{Status, Data, Req2} = cowboy_req:body(Req),
{{Status, Data}, Req2}
end
然后你必须检查,就像你之前做的那样,但是现在有了更多的语法,你不需要一个闭包,还有几行来分割结果并匹配它的内容,等等.HOIR ON火!啊!让我们把音量提高一个档次......
我觉得整件事情只是变得越来越复杂,所以可能会转向另一个方向,删除聪明的设备而不是添加它们,揭示了一些东西。让我们看看没有case
的情况:
body_to_client({ok, Data, Req}, ClientRef) ->
ok = hackney:send_body(ClientRef, Data),
Req;
body_to_client({more, Data, Req}, ClientRef) ->
ok = hackney:send_body(ClientRef, Data),
body_to_client(cowboy_req:body(Req), ClientRef).
现在body_to_client/2
是一个自己的命名案例。但是我们两次都做同样的事情(总是把数据发送到ClientRef),写两次感觉很傻。关于是否要迭代,实际上只有一个决策点。让我们提炼出来:
body_to_client({Status, Data, Req}, ClientRef) ->
ok = hackney:send_body(ClientRef, Data),
check_status({Status, Req} ClientRef).
check_status({ok, Req}, _) ->
Req;
check_status({more, Req}, ClientRef) ->
body_to_client(cowboy_req:body(Req), ClientRef).
现在一切都已命名,代码明确了每件作品的作用。如果check_status/2
看起来更具可读性,我们可以将body_to_client/2
作为case
传回[{1}}:
body_to_client({Status, Data, Req}, ClientRef) ->
ok = hackney:send_body(ClientRef, Data),
case Status of
ok -> Req;
more -> body_to_client(cowboy_req:body(Req), ClientRef)
end.
请注意,将作为命名函数正常工作的匹配作为case
引入另一个函数是有争议的。名称body_to_client
现在有点谎言,因为这个功能不仅仅是将主体发送到客户端(但这个谎言的性质可能也可能不重要,具体取决于代码的其余部分)。