首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何使用erlang fun递归函数?

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

Stack Overflow用户
提问于 2019-04-11 15:38:47
回答 2查看 93关注 0票数 1

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

代码语言:javascript
复制
fun (Fields, Bin) ->
    Parse =
        fun (P, F, <<Length, Rest/binary>>) ->
                P(P, F#{first => Length}, Rest)
        end,
    Parse(Parse, Fields, Bin)
end.

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

但是我的函数在使用滑稽技巧时并不能像预期的那样工作

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

EN

回答 2

Stack Overflow用户

发布于 2019-04-11 17:15:50

您在那里所做的实际上只是读出长度,而不是对Rest做太多事情。您需要首先声明一个退出条件,即当TLV为空时,->只返回累加器;然后使用模式匹配根据Length读出值

代码语言:javascript
复制
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]).

您可以使用上面的代码来读取值,并且可以执行类似的操作来首先获取类型,如下所示:

代码语言:javascript
复制
tlv(<<Type, Values/binary>>) ->
   %% Return at tuple with the Type and the values.
   {Type, parse(Values, [])}.
票数 1
EN

Stack Overflow用户

发布于 2019-04-11 17:08:40

您可以像这样编写函数:

代码语言:javascript
复制
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),并将其与数据字段列表一起返回。内部fun接受一个长度字节和相应数量的数据字节,返回数据并对其自身进行递归调用-直到它到达二进制的末尾。

内部的fun是一个“命名的fun":它自称为Parse,因此无需将自身作为参数传递即可调用自己。在乐趣之外,Parse这个名字是不可见的。有关详情和示例,请参阅this question

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/55627111

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档