【发布时间】:2016-04-12 08:43:00
【问题描述】:
如果我有一个用作命令行工具的程序,我有哪些调试选项?
为了这个例子,假设程序看起来像这样。
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 失败,并且程序以非零代码退出,程序员有哪些选择来确定哪个谓词失败?
answer linked in the comments 提供了一种解决方案。但是(如果我理解正确的话)这确实需要程序员系统地检查执行流程,直到找到有问题的谓词调用。
这正是我希望避免的。
【问题讨论】:
-
你看过this answer吗?
-
@false 我之前已经看过这个问题的两个答案。当我读到它时,你的绝对比使用
format更干净,但没有根本的不同:我仍然需要自己寻找失败的根源。我错过了什么? -
@false 但是我当然可以为“没有选择点的成功”定义一个符号/元谓词,并慷慨地使用它(也就是说,对于我知道的每个谓词都应该在没有选择的情况下成功观点);这会是一个合理的解决方案吗?
-
我不确定这个“完全”确定性的属性是否有用,您应该一直对其进行测试。通过偶尔测试,我发现这个属性相对容易维护。
-
@false 查看我的问题的编辑,我试图解释我的动机。
标签: debugging prolog swi-prolog failure-slice