Dean Meehan
Dean Meehan

Reputation: 2647

Creating sub-list from list in Prolog

I am having trouble understanding a concept in prolog.

I have a prolog list:

MyList = [item(dog,red), item(cat,black), item(rat,gray)]

and I am looking to create a list of just the colors i.e. [red,black,gray]

Currently the solution I have tried is:

getlistcolors([item(_,C)|T], Result) :-
    getlistcolors(T,Result),
    append([C],Result,Result).

getlistcolors([],_).

I would like to be able to call the function:

?- getlistcolors(MyList, Result).
Result = [red,black,gray]

Any help is appreciated.

Thanks

Upvotes: 0

Views: 504

Answers (2)

CapelliC
CapelliC

Reputation: 60034

Just to fix a problem in lurker comment:

when using setof/3 or bagof/3, you have to specify 'universal quantification' of each variable involved in the query, you're not interested in:

?- MyList = [item(dog,red), item(cat,black), item(rat,gray)],setof(Color, P^member(item(P, Color), MyList), ColorList).
MyList = [item(dog, red), item(cat, black), item(rat, gray)],
ColorList = [black, gray, red].

the missing quantification problem is better explained in the bagof section of inline documentation

A SWI-Prolog solution could make use of libraries yall and apply (both autoloaded, you don't have to worry about including them):

getlistcolors(List, Colors) :- maplist([E,C]>>(E = item(_,C)), List, Colors).

?- getlistcolors([item(dog,red), item(cat,black), item(rat,gray)],Cs).
Cs = [red, black, gray].

Upvotes: 1

max66
max66

Reputation: 66230

Try with

getlistcolors([], []).

getlistcolors([item(_,C)|T], [C | Result]) :-
    getlistcolors(T,Result).

You can't append the new find C color with

append([C],Result,Result)

because you're imposign that the second list and the appended list are equals.

You should use two different variables writing

getlistcolors([item(_,C)|T], Result) :-
    getlistcolors(T,HeadC),
    append([C],HeadC,Result).

but you can obtain the prepend-C effect simply translating C as head of the second argument

getlistcolors([item(_,C)|T], [C | Result]) :-

Second point wrong with your code: the terminal clause can't be written as

getlistcolors([], _).

or the second argument isn't unified with [] and the reasult become something like

[red,black,gray|_20]

where _20 is a variable that isn't unified.

Upvotes: 2

Related Questions