Recursion 如何使用erlang fun递归函数?
我正在尝试使用可变长度和选项解码帧(例如以太网帧中的TLV) 为了做到这一点,我考虑做一个有趣的递归函数:Recursion 如何使用erlang fun递归函数?,recursion,erlang,frame,Recursion,Erlang,Frame,我正在尝试使用可变长度和选项解码帧(例如以太网帧中的TLV) 为了做到这一点,我考虑做一个有趣的递归函数: fun (Fields, Bin) -> Parse = fun (P, F, <<Length, Rest/binary>>) -> P(P, F#{first => Length}, Rest) end, Parse(Parse, Fields, Bin) end.
fun (Fields, Bin) ->
Parse =
fun (P, F, <<Length, Rest/binary>>) ->
P(P, F#{first => Length}, Rest)
end,
Parse(Parse, Fields, Bin)
end.
fun(字段、Bin)->
解析=
乐趣(P,F,)->
P(P,F{first=>Length},Rest)
完,,
解析(解析、字段、Bin)
结束。
因此,Bin是输入帧,例如:40 02 12 45 01 50
因此,第一个字节是帧的类型,02
是以下数据的长度12 45
,01
是以下数据的长度50
,依此类推
但是我的函数使用这个有趣的技巧并没有像预期的那样工作
我返回JSON对象是因为它是通过MQTT发送的。您可以这样编写函数:
fun(<<Type, Packet/binary>>) ->
{Type,
fun Parse(<<>>) ->
[];
Parse(<<Length, Data:Length/bytes, Rest/binary>>) ->
[Data] ++ Parse(Rest)
end(Packet)}
end.
fun()->
{类型,
乐趣解析()->
[];
Parse()->
[数据]++解析(Rest)
结束(数据包)}
结束。
这将返回样本数据的{40,[,]}
外部函数获取帧类型(本例中为40),并将其与数据字段列表一起返回。内部函数获取一个长度字节和相应数量的数据字节,返回数据并对自身进行递归调用,直到到达二进制文件的末尾
内部的fun是一个“命名的fun”:它调用自己
Parse
,因此能够调用自己,而不需要将自己作为参数传递。名称Parse
在游戏外不可见。有关详细信息和示例,请参阅。您在那里所做的实际上只是读取长度,而对其余部分的处理不多。您需要首先声明退出条件,即当TLV为空->仅返回accummulator;并使用模式匹配根据长度
读取值:
parse(<<>>, Acc) -> Acc; %% finished with the list
parse(<<Length, Rest/binary>>, Acc) ->
<<Value:Length/binary, Carry/binary>> = Rest.
%% Value for the tag, Carry to be passed back on the recursion.
%% Assuming that `Acc` is a list of Values.
parse(Carry, Acc ++ [Value]).
parse(,Acc)->Acc;%完成列表
解析(,Acc)->
=休息。
%%要在递归中传回的标记Carry的值。
%%假设“Acc”是一个值列表。
解析(进位,Acc++[Value])。
您可以使用上面的命令来读取值,并且可以执行类似的操作来首先获取类型,如下所示:
tlv(<<Type, Values/binary>>) ->
%% Return at tuple with the Type and the values.
{Type, parse(Values, [])}.
tlv()->
%%返回具有类型和值的元组。
{Type,parse(值,[])}。