【发布时间】:2016-02-04 06:37:42
【问题描述】:
我有以下两个 Prolog 文件:
ontology.pl:
isSite(Url) :- string(Url).
guestPostPublished(GuestPostId, Date, Site, Url) :-
string(GuestPostId),
date(Date),
isSite(Site),
string(Url),
\+(guestPostPublished(GuestPostId, _, _, _)).
invalidFile.pl:
isSite('somesite.com').
guestPostPublished(
'gp1',
date(2016,2,2),
'somesite.com',
'someUrl').
guestPostPublished(
'gp1',
date(2016,2,2),
'somesite.com',
'anotherUrl').
invalidFile.pl 无效,因为它违反了ontology.pl 中指定的所有GuestPostIds 必须是唯一的规则。
当我将该数据加载到我的引擎中时,我会抛出一些异常,表明数据无效。但事实并非如此。
我做错了什么?如何确保当我将无效数据提供给 TuProlog 引擎时,我会收到某种通知(例如异常或某些标志)?
这是我的代码的相关片段(你可以找到整个代码here):
@Test
public void test2() throws InvalidObjectIdException, IOException,
MalformedGoalException, InvalidTheoryException, UnknownVarException, NoSolutionException,
NoMoreSolutionException, InvalidLibraryException {
final Prolog engine = createEngine();
try
{
loadPrologFiles(engine, new String[]{
"src/main/resources/ontology.pl",
"src/main/resources/invalidFile.pl"
});
Assert.fail("Engine swallows invalid Prolog file.");
}
catch (final Exception exception) {
// TODO: Check that the right exception is thrown
}
final List<String> result = getResults(engine, "guestPostPublished(_,X,_,_).", "X");
System.out.println("result: " + result);
}
private Prolog createEngine() throws InvalidObjectIdException {
final Prolog engine = new Prolog();
engine.addOutputListener(new OutputListener() {
public void onOutput(OutputEvent outputEvent) {
System.out.println(String.format("PROLOG: %s", outputEvent.getMsg()));
}
});
Library lib = engine.getLibrary("alice.tuprolog.lib.OOLibrary");
((OOLibrary)lib).register(new Struct("stdout"), System.out);
return engine;
}
private void loadPrologFiles(final Prolog engine, final String[] files) throws IOException, InvalidTheoryException {
final List<String> paths = Arrays.asList(files);
final StringBuilder theoryBuilder = new StringBuilder();
for (final String path : paths) {
theoryBuilder.append(System.lineSeparator());
theoryBuilder.append("% ");
theoryBuilder.append(path);
theoryBuilder.append(" (START)");
theoryBuilder.append(System.lineSeparator());
theoryBuilder.append(FileUtils.readFileToString(new File(path)));
theoryBuilder.append(System.lineSeparator());
theoryBuilder.append("% ");
theoryBuilder.append(path);
theoryBuilder.append(" (END)");
theoryBuilder.append(System.lineSeparator());
}
final Theory test1 = new Theory(theoryBuilder.toString());
engine.setTheory(test1);
}
private List<String> getResults(final Prolog engine, final String query, final String varName) throws
MalformedGoalException, NoSolutionException, UnknownVarException, NoMoreSolutionException {
SolveInfo res2 = engine.solve(query);
final List<String> result = new LinkedList<String>();
if (res2.isSuccess()) {
result.add(res2.getTerm(varName).toString());
while (engine.hasOpenAlternatives()) {
res2 = engine.solveNext();
final Term x2 = res2.getTerm("X");
result.add(x2.toString());
}
}
return result;
}
【问题讨论】:
-
通常的 Prolog 没有像关系数据库那样内置的数据完整性约束机制。除非 TuProlog 将其作为库提供,否则您不能只声明主键。你可以很容易地自己实现它,但是:数据库是动态的吗?它会在程序的生命周期内发生变化吗?您需要在该表中插入新行吗?
-
@Boris Prolog 文件在运行时不会更改。我想让程序做的是:读取一组 Prolog 文件并告诉我,它们是否符合
ontology.pl中指定的规则。然后,程序终止。 -
如果您咨询
invalidFile.pl,Prolog 假定内容建立事实 并且根据定义是真实的。如果您想将invalidFile.pl的内容视为查询,那么您需要读取文件并尝试调用每个事实并检查调用是否成功。 -
这取决于更广泛的背景,哪种方法更适合您的应用程序。我的建议假设您将有一个谓词,例如,读取一个试验事实文件并尝试调用它们,并且会(以某种方式)让您知道是否有失败,或者将提供失败事实的列表,或者任何你想要的(你还没有真正说过你想如何处理失败,单独或en masse)。 Boris 的解决方案假定您的数据库中已经有事实断言(例如,您已经咨询过
invalidFile.pl),您想质疑其有效性。 -
如果您想在咨询/断言其中有任何问题之前检查文件,那么我的建议将适用。