如何列出 Prolog 查询,然后以编程方式打印每个查询及其结果?

How to you list Prolog queries and then print each query and its result(s) programmatically?

我有以下名为 movies.pl 的文件:

acted_in('Brad Pitt', 'Babel').
acted_in('Cate Blanchett', 'Babel').
acted_in('Sharlto Copley', 'District 9').
acted_in('Sharlto Copley', 'Elysium').
acted_in('Matt Damon', 'Elysium').
acted_in('Sharlto Copley', 'Europa Report').
acted_in('Leonardo DiCaprio', 'Don\'t Look Up').
acted_in('Jonah Hill', 'Don\'t Look Up').
acted_in('Cate Blanchett', 'Don\t Look Up').
acted_in('Adam Sandler', 'Click').
acted_in('Christopher Walken', 'Click').
acted_in('Kate Beckinsale', 'Click').
acted_in('Jonah Hill', 'Click').
acted_in('Leonardo DiCaprio', 'The Aviator').
acted_in('Cate Blanchett', 'The Aviator').
acted_in('Kate Beckinsale', 'The Aviator').
acted_in('Brad Pitt', 'Inglourious Basterds').
acted_in('Melanie Laurent', 'Inglourious Basterds').
acted_in('Michael Fassbender', 'Inglourious Basterds').
acted_in('Diane Kruger', 'Inglourious Basterds').

directed('Alejandro Gonzalez Inarritu', 'Babel').
directed('Neill Blomkamp', 'District 9').
directed('Neill Blomkamp', 'Elysium').
directed('Sebastian Cordero', 'Europa Report').
directed('Adam McKay', 'Don\'t Look Up').
directed('Frank Coraci', 'Click').
directed('Martin Scorsese', 'The Aviator').
directed('Quentin Tarantino', 'Inglourious Basterds').

released('Babel', 2006).
released('District 9', 2009).
released('Europa Report', 2013).
released('Don\'t Look Up', 2021).
released('Click', 2006).
released('The Aviator', 2004).
released('Inglourious Basterds', 2009).

我想 运行 自动对其进行一系列查询,而无需我以交互方式输入查询。以交互方式输入时,一些示例查询如下所示:

?- released(Movie, 2009), directed(Director, Movie).
Movie = 'District 9',
Director = 'Neill Blomkamp' ;
Movie = 'Inglourious Basterds',
Director = 'Quentin Tarantino'.

?- acted_in(Actor, 'Click'), acted_in(Actor, 'The Aviator').
Actor = 'Kate Beckinsale' ;
false.

?- directed(Director_1, Movie), directed(Director_2, Movie), \+ Director_1 = Director_2.
false.

由于这些是 运行 交互式的,我知道询问了哪些查询并得到了哪些结果。当我以编程方式 运行 它们时,我基本上想要完全相同的输出,但生成每个结果的查询打印在它上面。搜索后,我看到了 initialization/1 指令的一些内容,但我不确定如何列出查询,然后将它们与结果一起打印出来。我对 Prolog 还是个新手,想继续阅读我正在阅读的这本书,而不会因为这种转移而陷入困境,尽管这种转移将有助于阅读本书。我只是想要一个我可以实现的简单的东西,这样我就可以 运行 加载文件时的查询列表,查询本身会被打印出来,然后是它们的结果。

谢谢!

实现此目的的一种方法是定义这两个辅助方法:

% Obtain one possible substitution ("Result") for Query
get_result(Query, Result) :-
    term_string(Term, Query, [variable_names(VariableNames)]),
    Term,
    Result = VariableNames.

% Find and print all substitutions for Query, fail if empty
log_query(Query) :-
    format("Evaluating: ~w ~n", [Query]),
    findall(Result, get_result(Query, Result), Results),
    not(length(Results,0)),
    writeln(Results).

有了这个我们可以为运行我们的查询定义一个谓词:

main :-
    log_query("released(Movie, 2009), directed(Director, Movie)."),
    log_query("acted_in(Actor, 'Click'), acted_in(Actor, 'The Aviator')."),
    log_query("directed(Director_1, Movie), directed(Director_2, Movie), \+ Director_1 = Director_2.").

然后将此子句添加到 运行 这个初始化谓词:

:- initialization main.

这将在会话开始时记录以下内容:

Evaluating: released(Movie, 2009), directed(Director, Movie). 
[[Movie=District 9,Director=Neill Blomkamp],[Movie=Inglourious Basterds,Director=Quentin Tarantino]]
Evaluating: acted_in(Actor, 'Click'), acted_in(Actor, 'The Aviator'). 
[[Actor=Kate Beckinsale]]
Evaluating: directed(Director_1, Movie), directed(Director_2, Movie), \+ Director_1 = Director_2. 
Warning: Initialization goal failed