我不确定如何进行事实和谓词的程序性和陈述性阅读。我想知道是否有人能给我一些如何写它们的指导。
这是我将Key
插入二叉树的代码:
insert(Key, null, tree(key, null, null)).
insert(Key, tree(Root, LST, RST), tree(Root, NewLST, RST)) :-
Key < Root,
insert(Key, LST, NewLST).
insert(Key, tree(Root, LST, RST), tree(Root, LST, NewRST)) :-
Key > Root,
insert(Key, RST, NewRST).
注意:二叉树的问题中存在OP代码的错误。问题是阅读Prolog代码而不是修复代码。
程序性阅读基于Bratko,第9.3节Insertion and deletion in a binary tree
pg。 231
T
是一棵二叉树。树可以是空的,只有一根,有一片叶子,或者有两片叶子。
insert(Key, null, tree(key, null, null)).
程序阅读:
将Key
插入空树null
的结果是树tree(key,null,null)
。
insert(Key, tree(Root, LST, RST), tree(Root, NewLST, RST)) :-
Key < Root,
insert(Key, LST, NewLST).
Proceduralreading:
如果T
的根大于Key
,则将Key
插入T
的左子树。
insert(Key, tree(Root, LST, RST), tree(Root, LST, NewRST)) :-
Key > Root,
insert(Key, RST, NewRST).
程序阅读:
如果T
的根小于Key
,则将Key
插入T
的右子树。
基于The Art of Prolog的声明性阅读,第3.4节Binary Trees
pg。 72
陈述性阅读:
Key
可以插入到空树中Key
小于节点处的值,则可以插入左子树Key
大于节点处的值,则可以插入到右子树中。关于为什么要写出声明性意义的个人说明很重要。
在尝试理解程序含义时,对我而言,它解释了代码如何在设置输入参数并返回值的过程模式下工作。
?- insert(5,null,Tree).
Tree = tree(5, null, null) ;
false.
注意:我修复了OP代码的错误,以使该查询能够像演示一样工作。
要么
?- insert(3,tree(5,null,null),Tree).
Tree = tree(5, tree(3, null, null), null) ;
false.
当试图理解声明性意义时,对我而言,它解释了代码如何在其他modes中工作,其中给出了结果,一个或多个参数是变量,或者所有参数都是变量(不记得这是什么叫做,我认为这是最普遍的问题)。
在这种情况下编写声明性含义,并尝试查询
?- insert(Key,X,tree(5,null,null)).
Key = 5,
X = null ;
ERROR: Arguments are not sufficiently instantiated
ERROR: In:
ERROR: [9] _8894<5
ERROR: [8] insert(_8920,tree(5,_8930,null),tree(5,null,null)) at c:/users/eric/documents/projects/prolog/so_question_101.pl:6
ERROR: [7] <user>
Exception: (8) insert(_8238, _8240, tree(5, null, null)) ? creep
和
?- insert(Key,Tree,tree(Root,Left,Right)).
Key = Root,
Tree = Left, Left = Right, Right = null ;
ERROR: Arguments are not sufficiently instantiated
ERROR: In:
ERROR: [9] _12488<_12490
ERROR: [8] insert(_12514,tree(_12522,_12524,_12526),tree(_12530,_12532,_12534)) at c:/users/eric/documents/projects/prolog/so_question_101.pl:6
ERROR: [7] <user>
% Execution Aborted
告诉我,其中一个或多个需要解决:
因此,通过学习如何将代码模式添加到从过程到声明的代码,人们也可以反过来看,这有助于在过程语言中编写更好的代码。
当我编写没有algebraic data types作为first class notion(如Java)的编程语言的代码时,我必须使用许多if
或switch
语句来涵盖数据结构的所有组合。现在有些情况下代码正确运行else
或default
,但为了使代码更好,当我写一个if
或switch
时,我总是添加else
或default
与assert (false)
并运行代码。如果断言失败,它通常表明我对代码的推理是错误的,我要么重写代码,要么将断言更改为注释,解释为什么else
或default
案例可以发生但不需要。