Reputation: 13038
Consider the following list:
[my,name,is,jack,baur]
I want to unify this to the following pattern:
[my,name,is,Name]
So that the variable Name has the value 'jack baur' in the end. The variable is working as some sort of wildcard here and should unify with an unknown number of atoms/list members.
Important:
Currently I have something like this:
rule([my,name,is,Name],[hello,Name]).
% Sentence is a list (e.g. [my,name,is,jack,baur]
answer(Sentence,Response) :-
rule(Sentence,ResponseList),
atomic_list_concat(ResponseList,' ',Response).
Obviously this only works when Name
is exactly one word, not two.
How would I approach this problem in Prolog?
Upvotes: 2
Views: 185
Reputation: 60034
here a DCG possibility. It's fairly clean, I think.
list(L) --> {length(L, _)}, L.
rule(R) -->
[my, name, is], list(Name),
[and, i, live, in], list(Country),
{flatten([hello, Name, of, Country],R)}.
rule([hello|Name]) -->
[my, name, is], list(Name) .
answer(Sentence, Response) :-
phrase(rule(Response), Sentence), !.
with that
?- answer([my, name, is, bill, the, kid, and, i, live, in, new, york],R).
R = [hello, bill, the, kid, of, new, york].
the essential production here is list//1, that matches any definite length list of tokens.
Beware: list(A),list(B),
, with both A, B unbound should be avoided.
It's ok instead if there are tokens in between, like in list(A),[and],list(B),
Upvotes: 1
Reputation: 363817
You need a custom unification algorithm, such as the following:
unify([], []).
unify([X|L], R) :-
(var(X) ->
% unify the variable X with some prefix of R
append(X, Tail, R),
;
R = [X|Tail],
),
unify(L, Tail).
Usage:
1 ?- unify([i, am, a, Profession, and, i, Verb, it],
[i, am, a, prolog, programmer, and, i, like, it]).
Profession = [prolog, programmer],
Verb = [like].
This algorithm only allows variables to occur in L
for the sake of efficiency. I'll leave the problem of pasting atoms together to you, since you seem to have already solved that.
Note that the current version allows variables to match zero atoms, but you can easily add a constraint to disallow that.
Upvotes: 1