Data structures 如何识别Prolog术语的浪费表示

Data structures 如何识别Prolog术语的浪费表示,data-structures,prolog,Data Structures,Prolog,什么是Prolog谓词,有助于显示Prolog术语的浪费表示 补充 除了前面的Prolog SO答案,IIRC by,它使用了一个Prolog谓词来分析一个Prolog术语,并说明它是如何过于复杂的 特别是像这样的术语 [op(add),[[number(0)],[op(add),[[number(1)],[number(1)]]]]] 它揭示了这对许多[]的影响 我已经搜索了我的序言问题,看了两遍答案,仍然找不到。我还记得,它不是在SWI Prolog中,而是在另一个Prolog中,因此,

什么是Prolog谓词,有助于显示Prolog术语的浪费表示


补充

除了前面的Prolog SO答案,IIRC by,它使用了一个Prolog谓词来分析一个Prolog术语,并说明它是如何过于复杂的

特别是像这样的术语

[op(add),[[number(0)],[op(add),[[number(1)],[number(1)]]]]]
它揭示了这对许多
[]
的影响

我已经搜索了我的序言问题,看了两遍答案,仍然找不到。我还记得,它不是在SWI Prolog中,而是在另一个Prolog中,因此,我没有安装另一个Prolog,而是能够使用带有Prolog的谓词

如果你在评论中阅读,你会发现mat识别了我正在寻找的


我在寻找什么

关于选择表示法,我还有最后一点要说明。请使用GnupLog或任何其他符合要求的序言系统,尝试以下内容:

| ?- write_canonical([op(add),[Left,Right]]). '.'(op(add),'.'('.'(_18,'.'(_19,[])),[])) 计算机程序员意识到,大多数编程语言在使用前必须解析数学表达式并将其转换为AST

add(add(X,0),sin(Y))
但是大多数编程语言不能像上面写的那样使用AST,必须创建数据结构,请参见:

现在,如果你在学习Prolog时所做的不仅仅是把脚趾浸在水里,那么你会遇到,这包括在,但是这个人没有给出归因

如果您尝试使用自己的代码来使用Prolog进行符号数学运算,您可能会尝试使用,但很快发现这不起作用,然后发现Prolog可以如下所示

这将开始工作,直到您需要访问和查找的名称,然后我们将返回到必须解析输入的位置,但是正如mat和中所述,如果要使结构的名称可访问

 op(add,(op(add,X,0),op(sin,Y)))
现在,我们不仅可以访问表达式的术语,还可以以Prolog友好的方式访问操作符

如果不是因为这个原因,代码仍将使用嵌套列表数据结构,现在正在转换为使用复合术语来公开结构的名称。我想知道是否有一个共同的短语来描述这一点,如果没有,应该有一个

无论如何,新的更简单的数据结构在第一组测试中起了作用,现在看看它是否能在项目进一步开发时保持住


自己在网上试试吧

在输入时使用

然后单击Execute并查看输出

sh-4.3$ gprolog --consult  file main.pg  
GNU Prolog 1.4.4 (64 bits)  
Compiled Aug 16 2014, 23:07:54 with gcc  
By Daniel Diaz  
Copyright (C) 1999-2013 Daniel Diaz  
compiling /home/cg/root/main.pg for byte code...  
/home/cg/root/main.pg:2: warning: singleton variables [Left,Right] for main/0  
/home/cg/root/main.pg compiled, 2 lines read - 524 bytes written, 9 ms  
'.'(op(add),'.'('.'(_39,'.'(_41,[])),[]))| ?-  


马库斯·特里斯卡

使用Prolog术语表示数据时,请自问以下问题:

我能区分每个组件的种类和它最外层的函子和算术吗?
如果这一点成立,您的表示将被称为clean。如果您不能通过最外层的函子和算术来区分元素,那么您的表示称为DDEFILITED,这是一种结合了“默认”和“错误”的文字游戏。这是因为对数据进行推理将需要一个“defaultcase”,如果其他所有操作都失败,则会应用该“defaultcase”。此外,这样的表示可以防止参数索引,并且由于这个缺点被认为是错误的。始终以避免默认表示为目标!以更清晰的表示形式为目标。

请参阅以下内容的最后一部分:

它使用
write_canonical/1
来显示aterm的规范表示

这个谓词在学习Prolog时非常有用,有助于澄清初学者常见的一些误解。例如,看看最近的一个问题,关于它在哪里也会有帮助


请注意,在SWI中,输出通常会偏离规范的Prolog语法,因此在解释Prolog语法时,我没有使用SWI。

您还可以使用类似的方法(未优化),通过编程计算单个元素列表中有多少子项

在示例复合词上进行尝试:

| ?- single_element_list_subterms([op(add),[[number(0)],[op(add),[[number(1)],[number(1)]]]]], Count).

Count = 7

yes
| ?-
指示由单个元素列表组成的7个子项。下面是写入规范的结果:

| ?- write_canonical([op(add),[[number(0)],[op(add),[[number(1)],[number(1)]]]]]).
'.'(op(add),'.'('.'('.'(number(0),[]),'.'('.'(op(add),'.'('.'('.'(number(1),[]),'.'('.'(number(1),[]),[])),[])),[])),[]))

yes
| ?-

一个术语是否“过于复杂”可能取决于该术语的上下文、用例和语义。例如,如果您想表示单个原子
a
,您可以很容易地认为
[[a]]]
这样的表示过于复杂(列表结构是多余的/不必要的)。然而,在更广泛的上下文中,如果对于为给定应用程序定义的更复杂的结构来说,
[[a]]]
是一个微不足道的例子,那么它可能是合适的。所以“过于复杂”的定义是什么?请链接到mat的post@lurker我认为最好的办法是避开将标题与序言术语联系在一起的整个问题,而仅仅是寻找一个古老的答案。我看到的问题是,答案对其他人有用,而一个标题是一个很好的吸引注意力的工具,它出现在谷歌搜索中。请随意更改标题;正如我之前注意到的,我认为我的所有帖子都是公开的、自由的,因为它们是创作共用的。我认为这是一个关于Prolog中的信息表示的刺激和有趣的问题,即使它有一个主观的成分,我很高兴你发表了它。构成一个好的(或者,也许是有效的)表示的可能是一些共同原则加上应用程序访问信息的需要的组合。。。我不知道我是否真的有一个更好的标题,现在我们已经挖了一点。所以我不去管它了。:)谢谢很好的例子。希望其他人从中学习,或者至少在不理解的情况下提问。
sh-4.3$ gprolog --consult  file main.pg  
GNU Prolog 1.4.4 (64 bits)  
Compiled Aug 16 2014, 23:07:54 with gcc  
By Daniel Diaz  
Copyright (C) 1999-2013 Daniel Diaz  
compiling /home/cg/root/main.pg for byte code...  
/home/cg/root/main.pg:2: warning: singleton variables [Left,Right] for main/0  
/home/cg/root/main.pg compiled, 2 lines read - 524 bytes written, 9 ms  
'.'(op(add),'.'('.'(_39,'.'(_41,[])),[]))| ?-  
single_element_list_subterms(Term, Index) :-
    Term =.. [Functor|Args],
    (   Args = []
    ->  Index = 0
    ;   maplist(single_element_list_subterms, Args, Indices),
        sum_list(Indices, SubIndex),
        (   Functor = '.', Args = [_, []]
        ->  Index is SubIndex + 1
        ;   Index = SubIndex
        )
    ).
| ?- single_element_list_subterms([op(add),[[number(0)],[op(add),[[number(1)],[number(1)]]]]], Count).

Count = 7

yes
| ?-
| ?- write_canonical([op(add),[[number(0)],[op(add),[[number(1)],[number(1)]]]]]).
'.'(op(add),'.'('.'('.'(number(0),[]),'.'('.'(op(add),'.'('.'('.'(number(1),[]),'.'('.'(number(1),[]),[])),[])),[])),[]))

yes
| ?-