【问题标题】:Turn a tuple into a list将元组变成列表
【发布时间】:2016-11-19 15:54:23
【问题描述】:

我已经搜索过,但奇怪的是没有找到太多关于此的内容。如何将未知长度的元组转换为序言中的列表?

例如:

List=[1,2,3,4], Tuple=(1,2,3,4).

【问题讨论】:

标签: list prolog tuples


【解决方案1】:

当您遇到术语转换时,最好了解一个术语实际上 的含义。

您可以使用 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) 形式的术语。

此外,在描述列表时,为方便起见,请始终考虑使用 表示法。

例如:

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,以便它在所有方向都可以作为练习。

【讨论】:

    【解决方案2】:

    您已经得到了两个有用的答案。如前所述,您通常不会在符号(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].
    

    【讨论】:

      【解决方案3】:

      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)).
      【解决方案4】:

      使用 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 仿函数执行相同的操作。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2013-01-31
        • 2022-08-18
        • 2017-09-16
        • 2022-06-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多