问题
I have an assignment to make a "simple" chatbot and my main problem now is in a predicate that receives a list of atoms (Ex: ["good","morning"]) and should return a list of possible answers that are already defined in structures. Also the predicate needs to filter for keywords and only return answer that contain keywords from the list given.
I have tried checking if an element from the list is already defined in any of the defined answers. If yes it would concat to the returning list. (This concat predicate was defined by the teacher and its basically the append/3 already defined).
ans("Hello there", 0).
ans("Hello",0).
ans("Hi",0).
ans("Good Morning",0).
ans("Good Afternoon",0).
ans("Good Night",0).
answer([], List).
answer([H|T], List):- ans(H, _), concat(List, H, List), answer([T], List).
When I run this with answer(["good"],List) and it runs to a infinite (I assume its a infinite loop because it takes a long time to run and give me an error saying that there no space left in stack) In this case the output should be ["Good Morning", "Good Afternoon", "Good Night"]. I appreciate all the help I can get.
回答1:
We've got a lot of issues here, starting with your question.
Without concat/3
and how you are calling your code, it really isn't possible for anyone to solve your problems. None of your predicates take a single argument, but you are saying the code goes into an infinite loop if you call it with one. So the best we can do is speculate until you improve your question with the missing detail.
Here's my speculated assumptions: concat/3
is probably append/3
. You are calling answer(["good"], Ans)
.
Looking at your code, concat(List, H, List)
looks very wrong to me, for two reasons:
- You are trying to mutate
List
, which is not possible in Prolog (variables cannot change once bound). - You are supplying a non-list in
H
to be concatenated toList
.
Another problem is that List
never receives an initial binding, so most likely you have to call this predicate with an argument of []
, which means you are treating it as both an input and an output value.
I think your intuition is on the right track here: it should be possible for you to find things by prefix using append/3
. Unfortunately, SWI-Prolog does not store strings as lists any more, so there is another predicate you have to use: string_concat/3
.
I don't think you can get the return value you want here easily. I think you need to use findall/3
or one of its friends to get multiple solutions, and if you are supplying a list of possible prefixes, you are going to get a list of lists of possible solutions. Perhaps I'm missing something obvious here. Anyway, this is the solution I found:
answer([], []).
answer([H|T], [Answers|R]) :-
findall(Answer,
(ans(Answer, _), string_concat(H, _, Answer)),
Answers),
answer(T, R).
This gives me the following output:
?- answer(["Good"], L).
L = [["Good Morning", "Good Afternoon", "Good Night"]].
Please correct your question so we can be more helpful to you!
来源:https://stackoverflow.com/questions/58823174/returning-list-of-possible-answers