如何设置 PrologScript

How to setup a PrologScript

我设置了以下规则来查找两个元素之间是否存在关系:

directReference(A,B) :- projectReferences(A,B).
transitiveReference(A,C) :- directReference(A,B),directReference(B,C).
transitiveReferenceD1(A,D) :- transitiveReference(A,C),directReference(C,D).
transitiveReferenceD2(A,E) :- transitiveReferenceD1(A,D),directReference(D,E).

我可以编写一个 PrologScript 来检查所有这些查询的事实吗?虽然我打算使用 Ruby&Rake,但有人试图从 PHP here and it has not worked. I also saw this answer 进行非交互式调用并尝试了 Kaarel 的回答。我刚刚添加了一个新的 opts_spec:

opts_spec(
    [ [opt(day), type(atom),
        shortflags([d]), longflags(['term', 'day']),
        help('name of day')]

    , [opt(goal),
        shortflags([g]), longflags([goal]),
        help('goal to be called')]

    , [opt(projectReferences), type(atom),
        shortflags([pr]), longflags(['term', 'projectReferences']),
        help('Project Reference lookup')]
    ]
).

然后我编译了:

.\swipl.exe -o day.exe -g main -c "D:\DevProjects\AskJoe\Output\Sample.pro"

并且 运行 它与:

./day.exe -g "day(Sunday)"

出现错误:

ERROR: Prolog initialisation failed: ERROR: validate_opts_spec/1: Domain error: unique_atom' expected, foundterm' (ambiguous flag)

我的目标是完成这项工作:

./day.exe -g "transitiveReference('a','b')"

我不喜欢将 "day.exe" 编译成 运行 脚本(according to the docs 这通常是不必要的),但我没有找到其他方法来将参数传递给规则.

我在 swi-pl.org 上看到了一个 basic intro,但没有多大帮助。它没有解释如何从 script.sh 文件示例跳转到 ./eval 1+2 的执行。事实上,这个例子是一个评论,所以我完全迷路了

这是一个非常粗略的 PrologScript 程序示例,它将其参数作为单个目标(可能是复合目标)读取,调用它,然后终止。它应该在 *nix 系统上工作,并且已经在 OS X 上进行了测试。它只是 example program 在 SWI 文档中使用 PrologScript 的一个细微变化:

#!/usr/bin/env swipl

:- initialization main.

query :-
        current_prolog_flag(argv, Argv),
        concat_atom(Argv, ' ', Atom),
        read_term_from_atom(Atom, Term, []),
        call(Term).

main :-
        catch(query, E, (print_message(error, E), fail)),
        halt.
main :-
        halt(1).


projectReferences(valueA, valueB) :- writeln('I was called!').
directReference(A,B) :- projectReferences(A,B).
transitiveReference(A,C) :- directReference(A,B),directReference(B,C).
transitiveReferenceD1(A,D) :- transitiveReference(A,C),directReference(C,D).
transitiveReferenceD2(A,E) :- transitiveReferenceD1(A,D),directReference(D,E).

将此文件另存为 cli_test.pl 后,您需要更改文件的权限,以便操作系统将其识别为可执行文件:

chmod -x scratchboard.pl

之后,您应该可以从命令行调用该文件作为普通可执行文件:

$ path/to/the/file/scratchboard.pl 'transitiveReferenceD1(A,D).'
I was called!

注:

  • 要评估的目标只是作为单个参数传递。 query/0 然后将使用 current_prolog_flag/2 检索此参数,将其作为 Prolog 术语读取并调用它。
  • 由于程序不是 运行 交互模式,唯一的输出将由显式命令写出,例如如果 catch/3 (在 main/0 的正文中) ) 由错误或 projectReferences/2 调用成功触发。

对于更复杂的 cli 界面,使用 library(optparse) 似乎是可取的,但对于您声明的仅在文件中查询目标的目标而言,这不是必需的。

我知道让 PrologScript 方法在 Windows 上工作有些不同。可以在这里找到一些信息:http://www.swi-prolog.org/FAQ/PrologScript.html

所以我让这一切正常工作,然后在运行几次之后一切都停止了。我开始收到 'permission denied bad interpreter' 错误。我只能说它与hashBang有关。我的解决方法是围绕对 swipl 的调用创建一个 shell 脚本:

shellscript.sh

#!/bin/bash
swipl -s script4.pl 'projectReferences(A,D).'

然后我继续使用aBathologist的例子,只是去掉了hashBang:

:- initialization main.

query :-
        current_prolog_flag(argv, Argv),
        concat_atom(Argv, ' ', Atom),
        read_term_from_atom(Atom, Term, []),
        call(Term).

main :-
        catch(query, E, (print_message(error, E), fail)),
        halt.
main :-
        halt(1).


projectReferences(valueA, valueB) :- writeln('I was called!').
directReference(A,B) :- projectReferences(A,B).
transitiveReference(A,C) :- directReference(A,B),directReference(B,C).
transitiveReferenceD1(A,D) :- transitiveReference(A,C),directReference(C,D).
transitiveReferenceD2(A,E) :- transitiveReferenceD1(A,D),directReference(D,E).