我是Prolog的新手,从终端启动prolog解释器的任务,输入consult(' some_prolog_program.pl'),然后测试你刚写的谓词非常耗时,是有没有办法运行脚本测试来加速开发?
例如在C中我可以写一个main我将使用我定义的函数,然后我可以执行:
make&& ./a.out
测试代码,我可以用Prolog做类似的事情吗?
答案 0 :(得分:6)
您可以始终打开解释器,然后重新编译该文件。
您可以在编译文件后自动运行谓词:
:- foo(4,2).
当在文件中遇到该行时,这将运行foo(4,2)
。
启动(大多数)Prolog解释器时可以使用标志,这些解释器允许您编译文件并运行谓词(查看手册页)。这样你就可以制作一个Bash脚本。以下内容将咨询file.pl
并使用SWI-Prolog运行foo/0
:
#!/bin/sh
exec swipl -q -f none -g "load_files([file],[silent(true)])" \
-t foo -- $*
此谓词将使用您在命令行中提供的标志列表统一Arguments:
current_prolog_flag(argv, Arguments)
但除非您要进行大量测试,否则我认为编写所有这些额外代码的速度会更快。
我个人非常喜欢在有或没有跟踪的情况下随时测试任何谓词的灵活性(参见trace/0
),而无需编写额外的代码来调用它们(与C不同)。
P.S。关于重新加载文件而不离开解释器:如果您使用了动态谓词或全局变量,则可能会遇到一些问题;你必须做一些清洁工作。
答案 1 :(得分:2)
您可以使用prolog +l <file>
此外,您可以构建一个run_tests
谓词来执行一系列调用,并根据预期结果验证实际结果。这是一篇文章,其中有一个很好的例子:http://kenegozi.com/blog/2008/07/24/unit-testing-in-prolog
答案 2 :(得分:2)
在SWI中,您可以照常加载内容。然后,当您编辑文件时,只需在顶层上说make.
,它会自动检查所有依赖项,并仅重新加载修改后的文件。
对于更大的项目,使用makefile确实很有意义。特别要做单元测试。请参阅SWI的包plunit。
答案 3 :(得分:1)
对于SWI-Prolog中的简单脚本,使用REPL 手动测试代码通常就足够了。更改的文件可以通过make/0
(?- make.
onplevel)重新加载。只需在编辑时保持Prolog REPL运行,然后保存编辑,在REPL中运行make.
并点击↑,↑,输入从历史记录make.
之前执行最后一次查询。
REPL的主要好处是它的互动性:
你可以摆弄这些论点。
转换到debugging or tracing(命令行和graphical)很容易。
您无需执行I / O即可打印结果。输出由顶层处理,打印替换。你会看到整个替代品,不仅仅是你碰巧打印的部分(可能会意外地忽略其他部分)。
您可以以交互方式选择要为多次成功的目标看到的替换次数。
很明显,在非确定性谓词返回的最后一个结果之后还有一个选择点,否则很难观察到。在这种情况下,在回溯到最后结果之后会打印false.
。
如果您需要保留测试调用以便稍后重复,create a protocol(交互式会话的记录或“日志”)并将其编辑为脚本,甚至是测试套件(见下文)。该协议是一个纯文本文件,包含终端的转义序列,包含您在交互式会话期间看到的内容的逐字副本。在Linux上使用cat protocol.txt
(以及其他* NIXes)或在Windows上使用type protocol.txt
查看协议。
如果不需要交互性,以非交互方式从命令行执行测试调用。让我们测试保存在factorial.pl
中的CLP(FD) factorial example n_factorial/2
(复制代码时不要忘记添加:- use_module(library(clpfd)).
):
$ swipl -q -t "between(0, 9, N), n_factorial(N, F), format('~D ', F), fail." factorial.pl
1 1 2 6 24 120 720 5,040 40,320 362,880
在Windows上,您可能需要指定swipl.exe
的完整路径,因为它可能不在PATH中。
如果调用始终相同,您可以将其保存到shell脚本或Makefile(run
将是目标的好名称。)
在当前用于测试C中函数的工作流程中,您创建一个新程序并从其入口点调用正在测试的函数(main
函数)。 Prolog脚本也可以有一个入口点。见library(main)
。 Prolog不需要编译,因此您可以直接调用脚本(./test.pl
)而无需先调用Make。
对于较大的项目,您可能希望创建一个不那么特别的测试套件。需要像PlUnit这样的单元测试框架。它的使用超出了这个答案的范围;见文档。