Reputation: 539
I am using a predicate that looks like this:
predicate(Country, X):-
setof(Length, anotherPredicate(Country,Length), X).
My problem here is that my code returns the list X for every value. What I want is to return a big list containing all the numbers because right now I get the answer:
Country = adsfsadf;
X = [123];
Country = asfdsaf;
X = [312];
So instead of small lists every time I want a big list containing it all.
EDIT for comment ----------
predicate(Country, Length) :-
setof(p(ML,C,L),
( anotherPredicate(C, L), ML is -L ),
[p(_,Country, Length)|_]).
This is what I wrote and it gives me false instantly.
Upvotes: 2
Views: 4500
Reputation: 10122
Currently you get one list for each solution of Country
. This is so, because setof/3
identifies all free variables and produces a list for each different instantiation of these variables.
But what you are asking is inconsistent. One the one hand you want to have only a single list. That is easy to provide, provided you can build the set of the solutions easily.
setof(Length, Country^anotherPredicate(Country,Length), X).
On the other hand you still want that Country
variable to be present as the first argument of predicate/2
! This does not make any sense. No more than to insist that a local variable be present in an outer context. Unfortunately, Prolog does not detect such errors directly. For with
predicate(Country, X):-
setof(Length, Country^anotherPredicate(Country,Length), X).
?- predicate(C, L).
L = [length_of_1, length_of_2].
?- C = c1, predicate(C, L).
C = c1, L = [length_of_1].
That is, by specializing the goal (by adding C = c1
), a different L
is found.
There is one caveat, however: What should be the result, if there are two countries with identical length, say 23? Do you want a single element [23]
or two [23,23]
? This is not clear from your description.
Should you want two, you will have to determine first:
setof(Country-Length, anotherPredicate(Country, Length), CL),
keys_values(CL, Lengths),
...
Edit: in response to your comment:
biggestcountry_val(Country, Length) :-
setof(p(ML,C,L),
( anotherPredicate(C, L), ML is -L ),
[p(_,Country, Length)|_]).
Upvotes: 3
Reputation: 74317
Without some sample data and expected/desired results, it's a bit hard to tell what you need. However...Examining the state of the argument in your predicate might give you what you're looking for.
For example, given this data:
foo( albania , 1 ) .
foo( albania , 2 ) .
foo( albania , 3 ) .
foo( albania , 4 ) .
foo( albania , 5 ) .
foo( albania , 6 ) .
foo( iceland , 4 ) .
foo( iceland , 5 ) .
foo( iceland , 6 ) .
foo( iceland , 7 ) .
foo( iceland , 8 ) .
foo( iceland , 9 ) .
foo( france , 7 ) .
foo( france , 8 ) .
foo( france , 9 ) .
foo( france , 10 ) .
foo( france , 11 ) .
foo( france , 12 ) .
Your initial cut at things shown in your question
predicate(Country, X):-
setof(Length, foo(Country,Length), X).
returns these multiple results when invoked with Country
being an unbound variable:
?- predicate(Country,X).
Country = albania , X = [1, 2, 3, 4, 5, 6] ;
Country = france , X = [7, 8, 9, 10, 11, 12] ;
Country = iceland , X = [4, 5, 6, 7, 8, 9] .
And this single result if invoked with Country
being bound to a valid country, iceland
in this case:
?- predicate(iceland,X).
X = [4, 5, 6, 7, 8, 9].
If you do something like this, however,
predicate( C , Xs ) :- var(C) , setof( X , C^foo(C,X) , Xs ) .
predicate( C , Xs ) :- nonvar(C) , setof( X , foo(C,X) , Xs ) .
You'll get this one solution when the argument is unbound:
?- try_this(C,Xs).
Xs = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12] ;
false.
You'll notice that C
remains unbound.
And you'll get this this one result when the argument is bound:
?- try_this(iceland,Xs).
Xs = [4, 5, 6, 7, 8, 9].
Upvotes: 2