Erlang 从复杂的元组/列表结构创建有效的函数声明
在Erlang中给定一个复杂对象,除了查看它之外,还有没有一种通用的方法为它提供一个有效的函数声明?我正在维护一些以前由巨型结构的狂热爱好者编写的代码,事实证明,手动执行这些代码很容易出错。 我不需要重复整个过程,只需要抓住顶层本身 例如,我现在正在做这个-Erlang 从复杂的元组/列表结构创建有效的函数声明,erlang,Erlang,在Erlang中给定一个复杂对象,除了查看它之外,还有没有一种通用的方法为它提供一个有效的函数声明?我正在维护一些以前由巨型结构的狂热爱好者编写的代码,事实证明,手动执行这些代码很容易出错。 我不需要重复整个过程,只需要抓住顶层本身 例如,我现在正在做这个- [[["SIP",47,"2",46,"0"],32,"407",32,"Proxy Authentication Required","\r\n"], [{'Via', [{'via-parm',
[[["SIP",47,"2",46,"0"],32,"407",32,"Proxy Authentication Required","\r\n"],
[{'Via',
[{'via-parm',
{'sent-protocol',"SIP","2.0","UDP"},
{'sent-by',"172.20.10.5","5060"},
[{'via-branch',"z9hG4bKb561e4f03a40c4439ba375b2ac3c9f91.0"}]}]},
{'Via',
[{'via-parm',
{'sent-protocol',"SIP","2.0","UDP"},
{'sent-by',"172.20.10.15","5060"},
[{'via-branch',"12dee0b2f48309f40b7857b9c73be9ac"}]}]},
{'From',
{'from-spec',
{'name-addr',
[[]],
{'SIP-URI',
[{userinfo,{user,"003018CFE4EF"},[]}],
{hostport,"172.20.10.11",[]},
{'uri-parameters',[]},
[]}},
[{tag,"b7226ffa86c46af7bf6e32969ad16940"}]}},
{'To',
{'name-addr',
[[]],
{'SIP-URI',
[{userinfo,{user,"3966"},[]}],
{hostport,"172.20.10.11",[]},
{'uri-parameters',[]},
[]}},
[{tag,"a830c764"}]},
{'Call-ID',"90df0e4968c9a4545a009b1adf268605@172.20.10.15"},
{'CSeq',1358286,"SUBSCRIBE"},
["date",'HCOLON',
["Mon",44,32,["13",32,"Jun",32,"2011"],32,["17",58,"03",58,"55"],32,"GMT"]],
{'Contact',
[[{'name-addr',
[[]],
{'SIP-URI',
[{userinfo,{user,"3ComCallProcessor"},[]}],
{hostport,"172.20.10.11",[]},
{'uri-parameters',[]},
[]}},
[]],
[]]},
["expires",'HCOLON',3600],
["user-agent",'HCOLON',
["3Com",[]],
[['LWS',["VCX",[]]],
['LWS',["7210",[]]],
['LWS',["IP",[]]],
['LWS',["CallProcessor",[['SLASH',"v10.0.8"]]]]]],
["proxy-authenticate",'HCOLON',
["Digest",'LWS',
["realm",'EQUAL',['SWS',34,"3Com",34]],
[['COMMA',["domain",'EQUAL',['SWS',34,"3Com",34]]],
['COMMA',
["nonce",'EQUAL',
['SWS',34,"btbvbsbzbBbAbwbybvbxbCbtbzbubqbubsbqbtbsbqbtbxbCbxbsbybs",
34]]],
['COMMA',["stale",'EQUAL',"FALSE"]],
['COMMA',["algorithm",'EQUAL',"MD5"]]]]],
{'Content-Length',0}],
"\r\n",
["\n"]]
使用模式匹配和用于列表的函数仅提取您需要的内容 看看:
keyfind
,keyreplace
,L=[H | T]
,…使用模式匹配和在列表上工作的函数,仅提取您需要的内容
看看:
keyfind
,keyreplace
,L=[H | T]
,…也许也许如果我理解正确,您希望模式匹配一些未知格式的大型数据结构
例如:
Input: {a, b} {a,b,c,d} {a,[],{},{b,c}}
function({A, B}) -> do_something;
function({A, B, C, D}) when is_atom(B) -> do_something_else;
function({A, B, C, D}) when is_list(B) -> more_doing.
当然,一般的答案是,仅仅从数据就知道如何对数据进行分类是不可判定的
首先,你应该了解暴力分子。它们是由诸如io_lib:format/2之类的函数以及代码中的许多其他地方创建的
一个例子是
[["SIP",47,"2",46,"0"],32,"407",32,"Proxy Authentication Required","\r\n"]
将打印为
SIP/2.0 407 Proxy Authentication Required
所以,我首先要用一个函数,比如
flatten_io(List) when is_list(List) ->
Flat = lists:map(fun flatten_io/1, List),
maybe_flatten(Flat);
flatten_io(Tuple) when is_tuple(Tuple) ->
list_to_tuple([flatten_io(Element) || Element <- tuple_to_list(Tuple)];
flatten_io(Other) -> Other.
maybe_flatten(L) when is_list(L) ->
case lists:all(fun(Ch) when Ch > 0 andalso Ch < 256 -> true;
(List) when is_list(List) ->
lists:all(fun(X) -> X > 0 andalso X < 256 end, List);
(_) -> false
end, L) of
true -> lists:flatten(L);
false -> L
end.
is\u List(List)时展平io(List)->
平面=列表:地图(趣味平面io/1,列表),
也许你会变平(变平);
当“是”时展平io(元组)->
列出_到_元组([展平_io(元素)| |元素其他)。
当列表(L)->
案例列表:当Ch>0且Ch<256->true时的所有(乐趣(Ch);
什么时候是列表
列表:全部(乐趣(X)->X>0,并且X<256结束,列表);
())->错
完(L)
正确->列表:展平(L);
假->L
终止
(警告:完全未经测试且效率很低。InProperter列表也会崩溃,但无论如何,数据结构中都不应该有这些列表。)
再想一想,我帮不了你。任何在字符串中使用原子“逗号”作为逗号的数据结构都应该取出并拍摄
你也应该能够将这些东西展平,并开始了解你所看到的东西
我知道这不是一个完整的答案。希望能有所帮助。如果我理解正确,您希望模式匹配一些未知格式的大型数据结构 例如:
Input: {a, b} {a,b,c,d} {a,[],{},{b,c}}
function({A, B}) -> do_something;
function({A, B, C, D}) when is_atom(B) -> do_something_else;
function({A, B, C, D}) when is_list(B) -> more_doing.
当然,一般的答案是,仅仅从数据就知道如何对数据进行分类是不可判定的
首先,您应该了解iolist,它们是由io_lib:format/2等函数以及代码中的许多其他地方创建的
一个例子是
[["SIP",47,"2",46,"0"],32,"407",32,"Proxy Authentication Required","\r\n"]
将打印为
SIP/2.0 407 Proxy Authentication Required
所以,我首先要用一个函数,比如
flatten_io(List) when is_list(List) ->
Flat = lists:map(fun flatten_io/1, List),
maybe_flatten(Flat);
flatten_io(Tuple) when is_tuple(Tuple) ->
list_to_tuple([flatten_io(Element) || Element <- tuple_to_list(Tuple)];
flatten_io(Other) -> Other.
maybe_flatten(L) when is_list(L) ->
case lists:all(fun(Ch) when Ch > 0 andalso Ch < 256 -> true;
(List) when is_list(List) ->
lists:all(fun(X) -> X > 0 andalso X < 256 end, List);
(_) -> false
end, L) of
true -> lists:flatten(L);
false -> L
end.
is\u List(List)时展平io(List)->
平面=列表:地图(趣味平面io/1,列表),
也许你会变平(变平);
当“是”时展平io(元组)->
列出_到_元组([展平_io(元素)| |元素其他)。
当列表(L)->
案例列表:当Ch>0且Ch<256->true时的所有(乐趣(Ch);
什么时候是列表
列表:全部(乐趣(X)->X>0,并且X<256结束,列表);
())->错
完(L)
正确->列表:展平(L);
假->L
终止
(警告:完全未经测试且效率很低。InProperter列表也会崩溃,但无论如何,数据结构中都不应该有这些列表。)
再想一想,我帮不了你。任何在字符串中使用原子“逗号”作为逗号的数据结构都应该取出并拍摄
你也应该能够将这些东西展平,并开始了解你所看到的东西
我知道这不是一个完整的答案。希望它能有所帮助。很难推荐解决这个问题的方法 将所有结构转换为更合理、更精简的格式似乎是值得的。这主要取决于这些结构的相似性 与其为100个部件中的每一个都有一个特殊的功能,还不如进行一些自动重新格式化,甚至可以将部件记录下来 一旦你有了记录,为它编写函数就容易多了,因为你不需要知道记录中元素的实际数量。更重要的是:当元素数量发生变化时,你的代码不会中断 总而言之:通过尽可能使用最通用的代码对它们进行消毒,在你的代码和这些结构的疯狂之间设置一道屏障。这可能是通用的重新格式化与特定结构的混合 在这个结构中已经可以看到一个例子:
'name-addr'
元组看起来有一个统一的结构。所以你可以在你的结构上递归(在元组和列表的所有元素上),匹配具有类似'name-addr'
的公共结构的“东西”,并用漂亮的记录替换它们
为了帮助您观察,您可以按照以下示例编写帮助器函数:
eyeball(List) when is_list(List) ->
io:format("List with length ~b\n", [length(List)]);
eyeball(Tuple) when is_tuple(Tuple) ->
io:format("Tuple with ~b elements\n", [tuple_size(Tuple)]).
因此,您将得到如下输出:
2> eyeball({a,b,c}).
Tuple with 3 elements
ok
3> eyeball([a,b,c]).
List with length 3
ok
在一个有用的工具中进行扩展供您使用,这只是一个练习。您可以通过在元素上递归并缩进输出来处理多个级别。很难推荐处理此问题的方法 将所有结构转换为更合理、更精简的格式似乎是值得的。这主要取决于这些结构的相似性 与其为100个部件中的每一个都有一个特殊的功能,还不如进行一些自动重新格式化,甚至可以将部件记录下来 一旦你有了记录,为它编写函数就容易多了,因为你不需要