我无法理解这段代码:
{<<"block">>, Els} ->
JIDs = parse_blocklist_items(Els, []),
process_blocklist_block(LUser, LServer, JIDs);
#1 parse_blocklist_items([], JIDs) -> JIDs;
#2 parse_blocklist_items([#xmlel{name = <<"item">>,
attrs = Attrs}
| Els],
JIDs) ->
case xml:get_attr(<<"jid">>, Attrs) of
{value, JID1} ->
JID = jlib:jid_tolower(jlib:binary_to_jid(JID1)),
parse_blocklist_items(Els, [JID | JIDs]);
false -> parse_blocklist_items(Els, JIDs)
end;
#3 parse_blocklist_items([_ | Els], JIDs) ->
parse_blocklist_items(Els, JIDs).
Run Code Online (Sandbox Code Playgroud)
我不确定首先调用哪个函数.
Els是空的,这意味着首先调用#3,然后调用#2,然后调用#3.对?为什么我们需要功能#3?如果#2已经返回JID,#3会有什么不同?我迷路了.
首先,一些术语:#1,#2并且#3被认为是不同的条款相同的功能.
这是编写递归函数的常用方法.该函数将输入列表中的一些(但不是全部)元素转换为其他元素.
#1是基本情况:如果没有更多的输入元素,我们只返回所有累积的输出元素(JIDs).
在#2,输入列表的第一个元素是xmlel其name字段为的记录<<"item">>.我们检查jid属性,如果有属性,我们创建一个JID并将其添加到列表中.请注意,我们使用递归调用:我们调用相同的函数,第一个参数是输入列表的其余元素,第二个参数是现有输出列表加上新添加的元素.
如果输入列表的第一个元素与模式不匹配#2,我们最终会进入#3,我们只是跳过它并继续处理列表的其余部分.
如果Els是空的,正如你在问题中提到的那样,那么我们最终会在子句中#1,并且实际上不会在#2和中命中代码#3.
子句#2和#3类似之处在于"消耗"输入列表中的元素.区别在于该子句#2 有时会为输出列表生成一个新元素,而子句#3 从不这样做.它们可以写成单个条款; 这是一个风格和偏好的问题.