提出问题的另一种方式是:
如何列出原子的所有属性?
例如:
movie(agora).
director(agora, 'Alejandro Amenabar')
duration(agora, '2h').
所以,我希望收到所有具有争论的集合的谓词。在这种情况下,它将是:电影,导演,持续时间,以及其他参数('Alejandro Amenabar','2h')。
如果PersonInvited不喜欢这部电影,我想在“变量答案”中获得false值。
我的查询将是:
answer(Answer, personInvited, personWhoMadeInvitation, Movie)
答:我不喜欢这位导演
answer(false, personInvited, personWhoMadeInvitation, Movie):-
director(Movie, DirectorName),not(like(personInvited,DirectorName)).
例如,像流派这样的任何属性都会发生同样的事情。
答:我不喜欢这种类型
answer(false, personInvited, personWhoMadeInvitation, Movie):-
genre(Movie, Genre), not(like(personInvited,Genre)).
所以,我想概括一下这种情况,而不是反复写出每个对象的每个特征。
答案 0 :(得分:2)
这是我的尝试,使用SWI-Prolog
?- current_predicate(so:F/N), N>0, length(As,N), Head =.. [F|As], clause(so:Head,Body), As=[A|_], A==agora.
请注意,我编码为模块,名为所以事实,因此我使用模块名称来限定相关调用。这样的内置(clause / 2和current_predicate / 1)符合ISO标准,而模块(SWI-prolog)则不符合ISO标准。所以我不确定可移植性等......
子句/ 2它是一个内置的,允许轻松写metainterprets。请参阅链接,了解该Prolog历史上的“力量点”的精彩介绍。
最后两次调用(我的意思是,As=[A|_], A==agora
)避免匹配具有变量作为第一个参数的子句。
答案 1 :(得分:2)
我发现两种解决方案,从我的观点来看,第二种解决方案更清洁,但它们是不同的。
<强>参数强>:
解决方案1 :
filter_predicate(PredName, Arity, ParamValue,PosParam, ListParam):-
current_predicate(PredName/Arity),
Arity >= PosParam,
nth(PosParam, ListParam, ParamValue),
append([PredName], ListParam, PredList),
GlobalArity is Arity + 1,
length(PredList, GlobalArity),
Predicate =.. PredList,
Predicate.
<强>查询强>
filter_predicate(PredName, Arity, agora, 1, Pm).
<强>输出强>
Arity = 2
Pm = [agora,'Alejandro Amenabar']
PredName = director ?
yes
<强>溶液2 强>:
filter_predicate(PredName, Arity, ParamList):-
current_predicate(PredName/Arity),
append([PredName], ParamList, PredList),
GlobalArity is Arity + 1,
length(PredList, GlobalArity),
Predicate =.. PredList,
Predicate.
查询1:
filter_predicate(PredName, Arity, [agora, X]).
<强>输出强>
Arity = 2
PredName = director
X = 'Alejandro Amenabar' ?
查询2:
filter_predicate(PredName, Arity, [X, 'Alejandro Amenabar']).
<强>输出强>
Arity = 2
PredName = director
X = agora ?
答案 2 :(得分:0)
使用reading lines into lists with prolog
所有谓词都在文件'my_file.pl'中。
e.g。 my_file.pl包含:
movie(agora).
director(agora, 'Alejandro Amenabar').
duration(agora, '2h').
您可以使用:
getLines(File,L):-
setup_call_cleanup(
open(File, read, In),
readData(In, L),
close(In)
).
readData(In, L):-
read_term(In, H, []),
( H == end_of_file
-> L = []
; L = [H|T],
readData(In,T)
).
pred_arg_file(Pred,Argue,File):-
getLines(File,L),
member(M,L),
M=..List,
member(Argue,List),
List=[Pred|_].
然后你可以查询:
?-pred_arg_file(Pred,agora,'my_file.pl').
Pred = movie ;
Pred = director ;
Pred = duration ;
false
或
?- findall(Pred,pred_arg_file(Pred,agora,'my_file.pl'),Preds).
Preds = [movie,director,duration].
如果要返回属性,请返回整个List而不仅仅是头部。
pred_arg_file(List,Argue,File):-
getLines(File,L),
member(M,L),
M=..List,
member(Argue,List).
答案 3 :(得分:0)
如果我理解你的问题,我建议如下:
如果您更改架构或遵循此想法,您可以制作一个模拟相同事物的方法。
class(movie, agora).
property(director, agora, 'Alejandro Amenabar').
property(duration, agora, '2h').
如果您想要agora的类型,查询将是:
class(Type, agora)
如果你想要agora的所有属性,那将是:
property( PropertyName, agora, Value).
答案 4 :(得分:0)
根据我的理解,你应该改变你的数据表示,以便你可以查询关系。正如其他答案所指出的那样,所以使用三元组,你可以轻松地编写代码,将你所有的关系改为这种形式。然后,您需要找出存储喜欢或不喜欢的最佳方式。这将影响否定的运作方式。在这个例子中:
relation(starwars,is,movie).
relation(lucas, directs,starwars).
relation(agora, is,movie).
relation('Alejandro Amenabar', directs, agora).
relation(agora, duration, '2h').
like(ma,'Alejandro Amenabar').
like(ma,movie).
like(ma,'2h').
ma_does_not_want_to_go(Film):-
relation(Film,is,movie),
relation(Film,_,Test), \+like(ma,Test).
ma_does_not_want_to_go(Film):-
relation(Film,is,movie),
relation(Test,_,Film), \+like(ma,Test).
ma_wants_to_go(Film):-
relation(Film,is,movie),
\+ma_does_not_want_to_go(Film).
sa_invites_ma(Film,true):-
ma_wants_to_go(Film).
sa_invites_ma(Film,false):-
ma_does_not_want_to_go(Film).
答案 5 :(得分:0)
使用Logtalk和GNU Prolog作为后端编译器的解决方案草案:
% a movie protocol
:- protocol(movie).
:- public([
director/1,
duration/1,
genre/1
]).
:- end_protocol.
% a real movie
:- object('Agora',
implements(movie)).
director('Alejandro Amenabar').
duration(120).
genre(drama).
:- end_object.
% another real movie
:- object('The Terminator',
implements(movie)).
director('James Cameron').
duration(112).
genre(syfy).
:- end_object.
% a prototype person
:- object(person).
:- public([
likes_director/1,
likes_genre/1
]).
:- public(likes/1).
likes(Movie) :-
conforms_to_protocol(Movie, movie),
( Movie::genre(Genre),
::likes_genre(Genre) ->
true
; Movie::director(Director),
::likes_director(Director) ->
true
; fail
).
:- end_object.
% a real person
:- object(mauricio,
extends(person)).
likes_director('Ridlye Scott').
likes_genre(drama).
likes_genre(syfy).
:- end_object.
一些示例查询:
$ gplgt
...
| ?- {movies}.
...
(5 ms) yes
| ?- mauricio::likes('Agora').
true ?
yes
| ?- mauricio::likes(Movie).
Movie = 'Agora' ? ;
Movie = 'The Terminator' ? ;
no
| ?- 'The Terminator'::director(Director).
Director = 'James Cameron'
yes
代码可以通过多种方式进行改进,但它应该足以让您清楚地了解评估此解决方案。