Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Debugging 调试命令行程序_Debugging_Prolog_Swi Prolog_Failure Slice_Zebra Puzzle - Fatal编程技术网

Debugging 调试命令行程序

Debugging 调试命令行程序,debugging,prolog,swi-prolog,failure-slice,zebra-puzzle,Debugging,Prolog,Swi Prolog,Failure Slice,Zebra Puzzle,如果我有一个用作命令行工具的程序,我的调试选项是什么 为了便于示例,让我们假设程序如下所示 do_stuff.pl列表: main :- current_prolog_flag(argv, Argv), do_stuff(Argv), halt. main :- halt(1). 使用SWI Prolog,我可以用以下方法编译: swipl --goal=main -o do_stuff -c do_stuff.pl 我只要打个电话就可以运行它 $ ./do_

如果我有一个用作命令行工具的程序,我的调试选项是什么

为了便于示例,让我们假设程序如下所示

do_stuff.pl
列表:

main :-
    current_prolog_flag(argv, Argv),
    do_stuff(Argv),
    halt.
main :-
    halt(1).
使用SWI Prolog,我可以用以下方法编译:

swipl --goal=main -o do_stuff -c do_stuff.pl
我只要打个电话就可以运行它

$ ./do_stuff foo bar baz
目前,如果
do_stuff/1
失败,将以1退出。我怎样才能看到第一个(最早、最深的)失败的目标?或者更好,整个回溯?我假设我应该能够使用
debug
leash
,例如:

main :-
    current_prolog_flag(argv, Argv),
    debug, leash(+fail),
    do_stuff(Argv),
    halt.
。。。但我没有尝试过任何有效的方法

我唯一一个半途而废的想法是,对我期望在确定性上成功但没有成功的每个谓词都抛出一个错误。这当然是可行的,但似乎有点过分

动机 用作命令行工具的程序(通常)要运行一次,获取其参数,读取其输入,写入输出。在这种情况下,失败意味着什么?我的理解是,意外的失败是程序中的错误

单元测试可能会有所帮助(单独测试谓词);但是,根据定义,这对由于程序员对问题、范围或工具缺乏了解而导致的错误没有帮助。只有使用真实输入运行程序才能捕获此类错误

因此,在上面的例子中,如果某个用例导致
do_stuff/1
失败,并且程序以非零代码退出,那么程序员在确定哪个谓词失败时有哪些选项

这个问题给出了一个解决方案。但是(如果我理解正确的话)这确实需要程序员系统地检查执行流,直到发现有问题的谓词调用为止


这正是我希望避免的。

与更多面向命令的语言相比,失败在Prolog中是非常不寻常的事情。从第一天开始,人们就对它感兴趣。事实上,即使在Prolog 0(Prolog I之前的版本)中,在跟踪选项
ECRIRE
旁边也有一个特殊的选项
僵局
,仅显示故障

后来,米雷尔·杜卡塞(Mirelle Ducasse)特别致力于自动找出故障的解释方法

失败的奇怪之处在于,它们并不一定表明出了什么问题。但有时,他们是

我要说的是,如何理解失败有两个不同的方向。第一个更具程序性,第二个更具声明性

注释 在许多项目中,我用它来表示我期望目标总是成功的。由于运算符声明,这只是一个额外字符:

   ...,
   @goal_aux_togoalaux_spec(OQuery, FVect0, Query, Spec),
   ...
如果目标失败,则会发出错误消息。同样重要的是,还要记录嵌套异常。如果出现时间紧迫的问题,则必须删除这些
@
。然而,我只是数了一下120kLOP中的~400

请注意,
@
对于有多个答案的目标也很有效。喜欢
@成员(1[X,Y])

这种技术适用于事实上的moded程序。想一想准备一个(这就是上面的例子)。在这里,你主要在想:这是一个程序,什么是合适的切片?在这种情况下,“不,没有切片”不是答案。你真的希望它永远成功。如果您没有这样的模式程序,您通常可以通过强制执行稳定性来转换现有的未安装模式程序:

p(X, Y) :-
   wellformed(X),
   @p_old(X, Yc),
   Yc = Y.
这种技术在纯关系、声明性代码中很快失去吸引力。看看这个。在那里,除了最初的目标之外,几乎不可能添加
@
。在这种情况下,需要一种更具声明性的方法,如下所示

概括 对于更复杂的问题,
@
的效果不太好。相反,需要对程序进行修改/切片。需要通过添加前缀
*
来概括程序。有关此类调试会话的集合,请参阅,以便手动使用此技术。 这种技术的要点是,在确定最大泛化时,您不必理解程序的真正含义。你只需要关注失败的目标


理想情况下,这样的概括会自动产生。然而,还有很多障碍。首先,它们只适用于纯单调代码(事实上,这是一个很好的动机,为什么人们应该坚持这样的代码)。因此,首先必须对现有代码进行分析和分类。如果系统不符合要求并随机改变其行为(如您提到的系统),这就更加困难了。

您看过吗?@false我以前见过这两个问题的答案。正如我所读到的,你的格式肯定比使用
格式更简洁,但并没有本质上的不同:我仍然需要自己寻找失败的根源。我遗漏了什么?@false,但我当然可以为“没有选择点的成功”定义一个符号/元谓词,并慷慨地使用它(也就是说,我知道的每个谓词都应该在没有选择点的情况下成功);这是一个合理的解决方案吗?我不确定“完全”决定论的这个属性是否有用,你应该一直测试它。我发现,通过偶尔测试,该属性相对容易维护。@false请参阅对我的问题的编辑,在那里我试图解释我的动机。因此,a)抛出任何应该总是成功一次的谓词,或b)开始在程序中查找错误。“随机改变他们的行为”这一点我没有体会到:几乎所有我有幸使用过的软件都有错误。找出错误是在您自己的代码中还是在其他地方是本练习的重点。@Bori