如何在序言中分配 return 变量?
How do I assign return variable in prolog?
我是 Prolog 的新手,所以我可能真的不在这儿。
我在过去一周试图解决以下问题:
tweeted(anne, tweet1).
tweeted(anne, tweet5).
tweeted(fred, tweet2).
tweeted(fred, tweet7).
tweeted(fred, tweet8).
findTweets(Name, TweetsByName) :- findall(X, tweeted(Name, X), TweetsByName).
tweets([], _).
tweets([Name|Names], Result) :-
findTweets(Name, Result),
/* how do I append Result to Result ? */
tweets(Names, Result).
如果我用单个变量调用,只有一个递归调用,我得到结果:
?- tweets([fred], R).
R = [tweet2, tweet7, tweet8].
但我很难理解如何将 findTweets 调用的结果值附加到结果,以便 return 累积结果?
我尝试使用 append
函数,但我没有运气......
例如:
tweets([], _).
tweets([Name|Names], Result) :-
findTweets(Name, Tweets),
append(Tweets, Result, Temp),
Result is Temp,
tweets(Names, Result).
但是我得到这个错误:
?- tweets([fred], R).
ERROR: Type error: `character' expected, found `tweet2' (an atom)
ERROR: In:
ERROR: [11] _25712 is [tweet2,tweet7|...]
ERROR: [10] tweets([fred],_25752) at /home/kimchi/git-repos/bbk/Programming-Language-Paradigms/logic-programming-Pavel-Durov/relationships.pl:33
ERROR: [9] toplevel_call(user:user: ...) at /snap/swi-prolog/43/usr/lib/swipl/boot/toplevel.pl:1117
提前致谢:)
我想你想要:
?- Names = [fred], findall(Tweet, (member(Name, Names), tweeted(Name, Tweet)), Tweets).
Names = [fred],
Tweets = [tweet2,tweet7,tweet8].
?- Names = [anne, fred], findall(Tweet, (member(Name, Names), tweeted(Name, Tweet)), Tweets).
Names = [anne,fred],
Tweets = [tweet1,tweet5,tweet2,tweet7,tweet8].
这里列出了 Names 发布的所有推文。
首先,几点说明:
is
仅 用于数字的算术计算。你不能在列表上使用它,你会得到一个错误。
- 您永远无法在 Prolog 中“重新分配”变量。如果您想为新术语命名,则始终需要使用新变量。
除此之外,您 append
的方向是正确的。我的解决方案和你的很接近,只是需要重新排列一下:
persons_tweets([], []).
persons_tweets([Person | Persons], AllTweets) :-
person_tweets(Person, ThisPersonTweets),
persons_tweets(Persons, OtherPersonsTweets),
append(ThisPersonTweets, OtherPersonsTweets, AllTweets).
我将你的 findTweets
重命名为 person_tweets
以更清楚地表明它是一个人与一组推文之间的关系。同样,persons_tweets
是人员集合(列表)与推文之间的关系。
示例:
?- persons_tweets([fred, anne], Tweets).
Tweets = [tweet2, tweet7, tweet8, tweet1, tweet5].
注意非递归的情况是persons_tweets([], []).
这里不能使用匿名变量_
。如果你有一个空的人员列表,你真的想要一个空的推文列表,而不仅仅是任何推文。例如,这应该会失败,但对于您的版本它会成功:
?- persons_tweets([], [some_tweet]).
false.
这里没有理由使用递归。您只需使用 findall/3
即可完成。尝试这样的事情:
tweet( anne , tweet1 ).
tweet( anne , tweet5 ).
tweet( fred , tweet2 ).
tweet( fred , tweet7 ).
tweet( fred , tweet8 ).
tweets( Ps , Ts ) :- findall(T,desired_tweet(Ps,T),Ts).
desired_tweet(Ps,T) :- tweet(P,T), member(P,Ps).
所以 tweets([fred],Ts)
产生预期的 Ts = [tweet1, tweet5, tweet2, tweet7, tweet8]
.
但如果作者列表是一个变量,它就会失败。如果 prolog 谓词的行为是对称的,那就太好了。所以让我们在这里添加几个助手:
这让用户可以将单个名称指定为原子(一个可能的常见用例):
tweets( P , Ts ) :- atom(P) , ! , tweets([P],Ts) .
这让用户将人员列表保留为未绑定变量,这将导致检索所有推文(并生成作者列表):
tweets( Ps , Ts ) :- var(Ps) , ! , setof(P,T^tweet(P,T),Ps) , tweets(Ps,Ts) .
[注:setof/3
调用中的表达式,T^tweet(P,T)
是一个存在量词。它告诉 setof/3
在确定集合时忽略 T
的值,因此您得到不同的 P
集合而不是不同的 [P,T]
对集合。
如果你把它们放在一起,
tweet( anne , tweet1 ).
tweet( anne , tweet5 ).
tweet( fred , tweet2 ).
tweet( fred , tweet7 ).
tweet( fred , tweet8 ).
tweets( P , Ts ) :- atom(P) , ! , tweets([P],Ts) .
tweets( Ps , Ts ) :- var(Ps) , ! , setof(P,T^tweet(P,T),Ps) , tweets(Ps,Ts) .
tweets( Ps , Ts ) :- findall(T,desired_tweet(Ps,T),Ts).
desired_tweet(Ps,T) :- tweet(P,T), member(P,Ps).
你可以说 tweets(anne,Ts)
并得到预期的 Ts = [tweet1, tweet5]
。
同样,你可以说 tweets(Ps,Ts)
并得到
Ps = [anne, fred],
Ts = [tweet1, tweet5, tweet2, tweet7, tweet8]
我是 Prolog 的新手,所以我可能真的不在这儿。 我在过去一周试图解决以下问题:
tweeted(anne, tweet1).
tweeted(anne, tweet5).
tweeted(fred, tweet2).
tweeted(fred, tweet7).
tweeted(fred, tweet8).
findTweets(Name, TweetsByName) :- findall(X, tweeted(Name, X), TweetsByName).
tweets([], _).
tweets([Name|Names], Result) :-
findTweets(Name, Result),
/* how do I append Result to Result ? */
tweets(Names, Result).
如果我用单个变量调用,只有一个递归调用,我得到结果:
?- tweets([fred], R).
R = [tweet2, tweet7, tweet8].
但我很难理解如何将 findTweets 调用的结果值附加到结果,以便 return 累积结果?
我尝试使用 append
函数,但我没有运气......
例如:
tweets([], _).
tweets([Name|Names], Result) :-
findTweets(Name, Tweets),
append(Tweets, Result, Temp),
Result is Temp,
tweets(Names, Result).
但是我得到这个错误:
?- tweets([fred], R).
ERROR: Type error: `character' expected, found `tweet2' (an atom)
ERROR: In:
ERROR: [11] _25712 is [tweet2,tweet7|...]
ERROR: [10] tweets([fred],_25752) at /home/kimchi/git-repos/bbk/Programming-Language-Paradigms/logic-programming-Pavel-Durov/relationships.pl:33
ERROR: [9] toplevel_call(user:user: ...) at /snap/swi-prolog/43/usr/lib/swipl/boot/toplevel.pl:1117
提前致谢:)
我想你想要:
?- Names = [fred], findall(Tweet, (member(Name, Names), tweeted(Name, Tweet)), Tweets).
Names = [fred],
Tweets = [tweet2,tweet7,tweet8].
?- Names = [anne, fred], findall(Tweet, (member(Name, Names), tweeted(Name, Tweet)), Tweets).
Names = [anne,fred],
Tweets = [tweet1,tweet5,tweet2,tweet7,tweet8].
这里列出了 Names 发布的所有推文。
首先,几点说明:
is
仅 用于数字的算术计算。你不能在列表上使用它,你会得到一个错误。- 您永远无法在 Prolog 中“重新分配”变量。如果您想为新术语命名,则始终需要使用新变量。
除此之外,您 append
的方向是正确的。我的解决方案和你的很接近,只是需要重新排列一下:
persons_tweets([], []).
persons_tweets([Person | Persons], AllTweets) :-
person_tweets(Person, ThisPersonTweets),
persons_tweets(Persons, OtherPersonsTweets),
append(ThisPersonTweets, OtherPersonsTweets, AllTweets).
我将你的 findTweets
重命名为 person_tweets
以更清楚地表明它是一个人与一组推文之间的关系。同样,persons_tweets
是人员集合(列表)与推文之间的关系。
示例:
?- persons_tweets([fred, anne], Tweets).
Tweets = [tweet2, tweet7, tweet8, tweet1, tweet5].
注意非递归的情况是persons_tweets([], []).
这里不能使用匿名变量_
。如果你有一个空的人员列表,你真的想要一个空的推文列表,而不仅仅是任何推文。例如,这应该会失败,但对于您的版本它会成功:
?- persons_tweets([], [some_tweet]).
false.
这里没有理由使用递归。您只需使用 findall/3
即可完成。尝试这样的事情:
tweet( anne , tweet1 ).
tweet( anne , tweet5 ).
tweet( fred , tweet2 ).
tweet( fred , tweet7 ).
tweet( fred , tweet8 ).
tweets( Ps , Ts ) :- findall(T,desired_tweet(Ps,T),Ts).
desired_tweet(Ps,T) :- tweet(P,T), member(P,Ps).
所以 tweets([fred],Ts)
产生预期的 Ts = [tweet1, tweet5, tweet2, tweet7, tweet8]
.
但如果作者列表是一个变量,它就会失败。如果 prolog 谓词的行为是对称的,那就太好了。所以让我们在这里添加几个助手:
这让用户可以将单个名称指定为原子(一个可能的常见用例):
tweets( P , Ts ) :- atom(P) , ! , tweets([P],Ts) .
这让用户将人员列表保留为未绑定变量,这将导致检索所有推文(并生成作者列表):
tweets( Ps , Ts ) :- var(Ps) , ! , setof(P,T^tweet(P,T),Ps) , tweets(Ps,Ts) .
[注:setof/3
调用中的表达式,T^tweet(P,T)
是一个存在量词。它告诉 setof/3
在确定集合时忽略 T
的值,因此您得到不同的 P
集合而不是不同的 [P,T]
对集合。
如果你把它们放在一起,
tweet( anne , tweet1 ).
tweet( anne , tweet5 ).
tweet( fred , tweet2 ).
tweet( fred , tweet7 ).
tweet( fred , tweet8 ).
tweets( P , Ts ) :- atom(P) , ! , tweets([P],Ts) .
tweets( Ps , Ts ) :- var(Ps) , ! , setof(P,T^tweet(P,T),Ps) , tweets(Ps,Ts) .
tweets( Ps , Ts ) :- findall(T,desired_tweet(Ps,T),Ts).
desired_tweet(Ps,T) :- tweet(P,T), member(P,Ps).
你可以说 tweets(anne,Ts)
并得到预期的 Ts = [tweet1, tweet5]
。
同样,你可以说 tweets(Ps,Ts)
并得到
Ps = [anne, fred],
Ts = [tweet1, tweet5, tweet2, tweet7, tweet8]