让我们用下面的序言基地:
father(anakinSkywalker, princessLeia).
father(anakinSkywalker, lukeSkywalker).
saysOhNo(lukeSkywalker).
sdesciencelover问如何显示的模式匹配的目标结果的SWI,序言从shell调用,并得到一个答案的查询给人一种人工改造,isue写。
swipl -q -s kb.pl -t "father(anakinSkywalker,X), writeln(X), false"
结果:
princessLeia
lukeSkywalker
这工作得很好,当一个只与一个自由变量几个疑问,但手动将每个一个很乏味,如果我们希望与每个变量的名称正确的输出,其结果一起,它很快变得很烦人。 例如运行查询father(AVariable, Another)
,一个需要写:
swipl -q -s kb.pl -t "father(AVariable,Another), write('AVariable='), write(AVariable), write(', Another='), writeln(Another), false"
结果:
AVariable=anakinSkywalker, Another=princessLeia
AVariable=anakinSkywalker, Another=lukeSkywalker
我试图从管道给它的命令,但它不工作的伟大(当它已经写完的结果我无法检测,所以它只是挂起之后,并没有换行分隔的答案):
(echo "father(X,Y)."; while true; do echo ";"; done) | swipl -q -s kb.pl
结果:
X = anakinSkywalker,
Y = princessLeia X = anakinSkywalker,
Y = lukeSkywalker.
swipl hangs here, and needs to be stopped with Control-C.
我知道我可以使用sed
脚本预先处理的查询,添加必要的代码来打印大写字母的变量,但它需要的工作有相当多的复杂的查询工作,例如在两个谓词必须满足:
father(X,Y), saysOhNo(Y).
要始终给出正确的结果,一个需要写序言解析器,这将是无用的工作,因为序言已经知道如何以交互方式做到这一点。
因此,这里是我的问题:有没有办法告诉GNU序言或SWI序言(或可以在Linux上轻松安装任何其他的免费版本)运行一些查询和打印结果,就像他们会以交互方式做,但不要求我输入(或复制粘贴)用手每个查询?
编辑:一种方法来存储一系列查询在一个文件中(无论是在kb.pl
文件或辅助文件),并运行它们,可见其效果会更好。
您可以使用命令行选项--query-goal
在GNU。 像这样:
$ echo a| gprolog --query-goal 'X = 1 ; X =2'
GNU Prolog 1.4.1
By Daniel Diaz
Copyright (C) 1999-2012 Daniel Diaz
| ?- X = 1 ; X =2.
X = 1 ? a
X = 2
yes
到目前为止,这里是我发现的方法:
在gprolog
使用虚假的答案 ,我发现有一个必须在顶部添加一行kb.pl
文件:
a(_) :- fail.
然后用./query.sh kb.pl "father(X,Y), saysOhNo(Y)"
其中query.sh
是:
#!/bin/sh
echo "a(fail)." | gprolog --query-goal "consult('$1'), $2"
当查询立即返回(即没有结果或一个结果和gprolog
管理,以检测它是最后一个),这将运行查询consult('kb.pl'), actual_query.
,然后运行查询a(fail).
这将简单地打印的外来no
在控制台上,这要归功于我们在文件的顶部添加了总是假的谓词。
当gprolog
问做什么(即多个结果,或一个结果和gprolog
无法检测到它是最后一个),这将运行查询consult('kb.pl'), actual_query.
,读a
它要求gprolog
打印所有结果,然后它会运行查询(fail).
这将简单地打印的外来no
在控制台上,因为这些都只是分组括号,所以查询等同于fail.
。
在xsb
人们可以使用./query.sh kb.pl "father(X,Y), saysOhNo(Y)"
其中query.sh
是:
#!/bin/sh
(echo "consult('$1'), ${2%.}."; yes halt.) | xsb --noprompt --quietload --nobanner
当xsb
询问下一步该怎么做,如果用户键入一个非空字符串,然后enter
,将打印下一个结果,否则将停止搜索解决方案,以当前查询。 因此,在yes halt.
命令,我们类型的非空行无限流。 xsb
将打印所有结果查询(每次读halt.
,所以它是一个非空字符串,它会在下一结果继续),并返回到它的提示。 接着,下面的halt.
它接收会告诉它退出。
在swi-prolog
我还没有找到一个解决办法。
[言论]这一切会这么简单得多,如果人民建设序言实现真正想过用他们非交互,比如它可能与大多数其他语言。[/言论]
你可能会发现你的问题的解决方案,但无论如何,在这里不用我的方法。 您可以随时递归到bagof内置谓词。 你可以看它做什么的文档,这样你会更多地了解它。
swipl -q -s starwars.pl -t "bagof(X, Y^father(X,Y), BagOfFathers), bagof(Y, X^father(X,Y), BagOfChildren), writeln(BagOfFathers), writeln(BagOfChildren)."
[anakinSkywalker,anakinSkywalker]
[princessLeia,lukeSkywalker]
您也可以处理它以后,只要你想映射或什么的,关系是1:1(不知道是否是说明它的正确的方式,但我希望你能得到它)
您可以使用SWI-序言以下bash脚本:
#!/bin/sh
exec swipl -q -f none -g "load_files([interface],[silent(true)])" \
-t interface:get_args -- $*
这将加载该文件interface.pl
并调用谓词get_args/0
得到命令行参数,你可以拨打:
current_prolog_flag(argv, Arguments)
当然,你可以改变谓词的名称/文件加载。
在silent(true)
参数抑制信息消息如介绍文字
编辑:您收到错误消息,因为你可能不具有interface.pl
文件(既不是get_args / 0谓词)。 你将不得不更换interface
与kb
(或者无论你命名的文件)和interface:get_args
与kb:father(X,Y), saysOhNo(Y)
或你的序言文件中使用的辅助谓词,如run(X,Y):- father(X,Y), saysOhNo(Y)
其可以是有点儿清洁器)
文章来源: How do I show the results of pattern-matching goals with several free variables in SWI-Prolog from a shell invocation?