1

bson-erlang模块将 BSON 编码的 JSON 转换为如下所示:

{ "salutation" : "hello",
  "subject" : "world" }

像这样进入 Erlang 元组:

{ salutation, <<"hello">>, subject, <<"world">> }

现在,我试图与之交谈的服务器可以将这些字段按任何顺序排列,并且其中可能有我不关心的额外字段,所以 - 同样有效 - 我可能会看到这个:

{ subject, <<"world">>, salutation, <<"hello">>, reason, <<"nice day">> }

有没有什么方法可以指定一个函数模式来提取元组的特定部分,基于它之前出现的那个?

如果我尝试以下操作,它会因“没有函数子句匹配...”而失败,因为元组的元数是错误的,并且因为我关心的字段不在正确的位置:

handle({ salutation, Salutation, _, _ }) -> ok.

这可能吗?有一个更好的方法吗?

4

2 回答 2

0
T = { subject, <<"world">>, salutation, <<"hello">>, reason, <<"nice day">> },
L = size(T),
L1 = [{element(I,T),element(I+1,T)} || I <- lists:seq(1,L,2)].

[{subject,<<"world">>},
 {salutation,<<"hello">>},
 {reason,<<"nice day">>}]

proplists:get_value(salutation,L1).                           
<<"hello">>

如果你想全在 1:

F = fun(Key,Tup) -> proplists:get_value(Key,[{element(I,Tup),element(I+1,Tup)} || I <- lists:seq(1,size(Tup),2)]) end.

F(reason,T).
<<"nice day">>
F(foo,T).
undefined
于 2013-10-09T13:27:37.777 回答
0

在未知长度的前缀之后,没有任何模式可以成功匹配可变长度结构中的值。元组、列表和二进制文件都是如此。实际上,这种模式需要通过结构递归。

列表的一种常见方法是通过拆分头尾进行递归,这是函数式语言的典型特征。

f_list([salutation, Salutation | _]) -> {value, Salutation};
f_list([_Key, _Value | Tail]) -> f_list(Tail);
f_list([]) -> false.

请注意,如果列表包含奇数个元素,此函数可能会失败。

元组也可以使用相同的方法,但是您需要保护而不是匹配模式,因为没有模式可以提取与元组尾部等效的内容。实际上,元组不是链表,而是具有 O(1) 访问其元素(及其大小)的结构。

f_tuple(Tuple) -> f_tuple0(Tuple, 1).

f_tuple0(Tuple, N) when element(N, Tuple) =:= salutation ->
    {value, element(N + 1, Tuple)};
f_tuple0(Tuple, N) when tuple_size(Tuple) > N -> f_tuple0(Tuple, N + 2);
f_tuple0(_Tuple, _N) -> false.

同样,如果元组包含奇数个元素,此函数可能会失败。

但是,基于问题中的要素,守卫的优势bson:at/2尚不清楚。

于 2013-10-14T11:53:27.477 回答