在Python中,从JSON封送对象是很常见的。我在Prolog中寻求类似的功能,无论是swi-prolog
还是scryer
。
例如,如果我们有JSON声明
{'predicate':
{'mortal(X)', ':-', 'human(X)'}
}
我希望找到类似load_predicates(j)的东西,并立即咨询该数据。json.dumps()
和loads()
的版本也将非常有用。
编辑:为了清楚起见,这将允许与从用户收集规则的客户端应用程序的互操作性。这个应用程序可能不是在Prolog中,而是像React.js这样的东西。
我同意评论者的意见,首先将JSON数据转换为正确格式的.pl
文件,然后加载它会更容易。
但是,您可以直接从JSON中加载谓词,将它们转换为Prolog可以理解的表示形式,并使用assertz
将它们添加到知识库中。
如果数据确实包含谓词所需的所有语法(如问题中的示例数据中的情况),那么转换表示就相当简单,因为您只需要将列表的元素连接到字符串中,然后从字符串中创建一个术语。注意,在Guy Coder的第一条注释中,这个假设跳过了第2步。
请注意Prolog JSON库在接受的格式上是相当严格的:只有双引号可以作为字符串分隔符,单值列表(即不是键值对)需要使用[a,b,c]
而不是{a,b,c}
符号。因此,首先需要重写示例数据:
{"predicate":
["mortal(X)", ":-", "human(X)"]
}
然后你可以在SWI-Prolog中加载它。最小工作示例:
:- use_module(library(http/json)).
% example fact for testing
human(aristotle).
load_predicate(J) :-
% open the file
open(J, read, JSONstream, []),
% parse the JSON data
json_read(JSONstream, json(L)),
% check for an occurrence of the predicate key with value L2
member(predicate=L2, L),
% concatenate the list into a string
atomics_to_string(L2, S),
% create a term from the string
term_string(T, S),
% add to knowledge base
assertz(T).
示例运行:
?- consult('mwe.pl').
true.
?- load_predicate('example_predicate.json').
true.
?- mortal(X).
X = aristotle.
详细解释:
谓词json_read
以以下形式存储数据:
json([predicate=['mortal(X)', :-, 'human(X)']])
这是json
术语中的一个列表,每个键值对有一个元素。元素的语法为key=value
。在对json_read
的调用中,您已经可以剥离json()
项并将列表直接存储在变量L
中。
则使用member/2
搜索复合词predicate=L2
。如果JSON文件中有多个谓词,那么应该将其转换为foreach或递归调用,以处理列表中的所有谓词。
由于列表L2
已经包含一个语法格式良好的Prolog谓词,它可以直接连接,使用term_string/2
转换为术语并断言。注意,如果谓词还不是所需的格式,您可以使用内置的谓词操作功能从各个部分构造一个谓词,参见https://www.swi-prolog.org/pldoc/doc_for?object=copy_predicate_clauses/2获取一些指针。