Recursion 如何使用erlang fun递归函数?

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.

我正在尝试使用可变长度和选项解码帧(例如以太网帧中的TLV) 为了做到这一点,我考虑做一个有趣的递归函数:

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(值,[])}。