【发布时间】:2016-11-19 15:54:23
【问题描述】:
我已经搜索过,但奇怪的是没有找到太多关于此的内容。如何将未知长度的元组转换为序言中的列表?
例如:
List=[1,2,3,4], Tuple=(1,2,3,4).
【问题讨论】:
我已经搜索过,但奇怪的是没有找到太多关于此的内容。如何将未知长度的元组转换为序言中的列表?
例如:
List=[1,2,3,4], Tuple=(1,2,3,4).
【问题讨论】:
当您遇到术语转换时,最好了解一个术语实际上 的含义。
您可以使用 write_canonical/1 获取术语的规范形式。
在你的情况下:
?- 元组 = (1,2,3,4), write_canonical(Tuple)。 ','(1,','(2,','(3,4))) 元组 = (1, 2, 3, 4)。这清楚地表明我们实际上是在讨论(A,B) 形式的复合术语——用前缀表示法写成','(A,B)——其参数是整数或再次这样的复合术语。这些术语在 Prolog 中也称为“and lists”,Prologgoals 也有这样的形状。请特别注意,这些并不是真正的“元组”,当然也不是“一等公民”意义上的,只是类似于任何其他复合词的复合词。
因此,我们只需要推理这2种可能的情况:
(A,B) 形式的术语。此外,在描述列表时,为方便起见,请始终考虑使用dcg 表示法。
例如:
tuple_list(I) --> { integer(I) }, [I]. tuple_list((A,B)) --> tuple_list(A), tuple_list(B)。现在我们有了:
?- 元组 = (1,2,3,4), 短语(tuple_list(Tuple), Ls)。 元组 = (1, 2, 3, 4), Ls = [1, 2, 3, 4]。这解决了您将此类术语转换为列表的任务。
但是,最一般的查询没有答案:
?- 短语(元组列表(元组),Ls)。 错误:超出本地堆栈我不再概括tuples_list//1,以便它在所有方向都可以作为练习。
【讨论】:
您已经得到了两个有用的答案。如前所述,您通常不会在符号(1, 2, 3, 4) 中使用“元组”:这不是像 Haskell 中那样的平面数据结构,它是嵌套数据结构。 Prolog 的方式是使用一个具有 4 个元数的术语,例如,quadruple(1, 2, 3, 4)。名称当然无关紧要,但通常情况下,您会使用某种描述性名称。
然后,要将术语的参数转换为列表,您可以像这样使用“univ”运算符=..:
Term =.. [Name|Arguments]
所以:
?- foo(1, 2, 3, 4) =.. [foo|Args].
Args = [1, 2, 3, 4].
在具有两个元素(对)的元组的特殊情况下,通常使用函子-/2。破折号也是一个中缀运算符,因此您可以写成1-a 而不是-(1, a)。相当多的对对起作用的库谓词期望它们为-/2,例如:
?- keysort([1-c, 2-a, -(0, b), 1-a], S).
S = [0-b, 1-c, 1-a, 2-a].
【讨论】:
Prolog 中的元组很少使用,但可以快速转换
list_tuple([A,B|L], (A,R)) :- list_tuple([B|L], R).
list_tuple([A,B], (A,B)). % I don't think unary tuples make sense...
?- list_tuple([1,2,3,4],T).
T = (1, 2, 3, 4) ;
false.
这在“向后模式”上效果不佳
?- list_tuple(L,(1,2,3,4)).
L = [1, 2, 3, 4] ;
L = [1, 2, (3, 4)] ....
您可以尝试进行切割以使其具有确定性,我已根据需要按顺序提供了子句...
【讨论】:
list_tuple([A,B,C|L], (A, R)) :- R = (B, _), !, list_tuple([B,C|L], R). list_tuple([A,B], (A,B)).
使用 SWI-Prolog,可以使用内置库谓词 comma_list/2 转换“元组”和列表。
comma_list(C, [1, 2, 3]).
% C = (1, 2, 3).
comma_list((1, 2, 3), L).
% L = [1, 2, 3].
comma_list((a, foo(bar), C), [a, B, c]).
% C = c,
% B = foo(bar).
有关更多使用示例,请参阅documentation。
搜索起来可能有点棘手,因为文档不一定将像 (1, 2, 3) 这样的术语称为“元组”,而是将它们描述为“,/2 函子上的嵌套术语”。还提供了semicolon_list/2,它将使用;/2 仿函数执行相同的操作。
【讨论】: