如何使用Erlang Fun递归函数?

时间:2019-04-11 07:38:47

标签: recursion erlang frame

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

40 02 12 45 01 50

因此Bin是输入帧,例如:02 因此,第一个字节是帧的类型,12 45是后续数据01的长度,50是长度是后续数据{{1}}的长度,依此类推。

但是使用有趣的技巧后,我的功能无法正常工作

我正在返回JSON对象,因为它是通过MQTT发送的。

2 个答案:

答案 0 :(得分:1)

您在这里所做的实际上只是读出长度,而对Rest所做的却不多。您需要首先声明退出条件,即当TLV为空时->仅返回累加器;并使用模式匹配来基于Length读取值:

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]).

您可以使用上面的方法读取值,并可以执行类似的操作以首先获取类型:

tlv(<<Type, Values/binary>>) ->
   %% Return at tuple with the Type and the values.
   {Type, parse(Values, [])}.

答案 1 :(得分:0)

您可以这样编写函数:

fun(<<Type, Packet/binary>>) ->
        {Type,
         fun Parse(<<>>) ->
                 [];
             Parse(<<Length, Data:Length/bytes, Rest/binary>>) ->
                 [Data] ++ Parse(Rest)
         end(Packet)}
end.

这将为您的示例数据返回{40,[<<12,45>>,<<50>>]}

外部乐趣采用帧类型(在这种情况下为40),并将其与数据字段列表一起返回。内部乐趣获取一个长度字节和相应数量的数据字节,然后返回数据并对其进行递归调用-直到到达二进制末尾为止。

内部乐趣是一个“命名的乐趣”:它自称为Parse,因此可以调用自己而无需将自身作为参数传递。名称Parse在娱乐之外看不到。有关详细信息和示例,请参见this question