Coding problem

Good points. I’d like to add two more

  • When looking at the findall/3 as alternative to maplist(convert,List,Ys) we should note that an unexpected failure of convert/2 silently looses an answer. A complete failure is way easier to find and debug than a slightly different answer. For the same reason it is often wise to use forall/2 rather than classical failure driven loops.

    findall(Y, (member(X,List), convert(X,Y)), Ys)
    
  • Be aware that using findall/3, bagof/3, etc. copies your data. If it is ground data that merely wastes space and time. findall/3 creates fresh variables. bagof/3 and setof/3 preserve these variables, but as the cost of even more copying. Things get even harder when attributed variables are involved. In some cases you can freely copy these but some constraint solvers may have expectations of the constraint network that are violated by copying.

So, if you have a list of stuff it is typically desirable to use maplist/2, include/3 and related meta predicates to turn it into another list. In many cases a set of answers to a query is a more desirable representation of a set though as you can use simple plain logic to filter, extend or transform this set. Moreover you can deal with infinite sets as you are basically streaming data.

5 Likes

Further to your help, I was tried to do something like this.
First of all, thank you for your detailed answers and your patience, I learn a lot from this. :slightly_smiling_face:
I have this problem that my output is duplicated to many times instead to print one time
HERE
I know this is not like you told me, I will fix it at the end, according to your explanations.
In my code I have few facts and then I want to check if x_lt_y
for all y
If is true, I want to print an HERE and then stop with fail (Because I want that my program will continue to another check rule)
The first use of findall found all the facts that x_lt_y(a, X).
The second use of findall found all the facts that some_fact_s of specific name value is bigger then a value.
Hopefully you can help me understand why it’s return back and print the same.
(I tried to debug but I didn’t understand)

Code:

x_lt_y(a, b).
x_lt_y(a, c).


some_fact_s(b, 5).			% (name, start_value)
some_fact_s(c, 6).			% (name, start_value)
some_fact_s(a, 1).			% (name, start_value)
some_fact_e(a, 2).			% (name, end_value)


is_not_empty(List) :- 																	
	member(_,List).

check(A, _a_end) :- 
	findall(B, x_lt_y(A, B), Result),
	format("~k~n", [Result]),
	is_not_empty(Result),
	findall(X, (member(X, Result), some_fact_s(X, _b_start), _b_start > _a_end), Result2),
	is_not_empty(Result2),
	format("[HERE]~n", []),
	fail.


check(A, _a_start) :- 
.
.
.
.

Output:

?- check(a, 2).
[b,c]
[HERE]
[HERE]
[HERE]
[HERE]
false.

can be done more simply and efficiently, and without creating an extra choicepoint:

is_not_empty([_|_]).

Somewhat advanced topic:
You might think that this would do the same:

is_not_empty(List) :- List \= [].  % danger!

but there are subtle problems with using negation. Negation is not a beginner’s topic, so I won’t say more (if you really want to know more, see dif/2; but I really really recommend becoming more comfortable with basic concepts first).

1 Like

I have opened a new question about my last problem

Thank you all for your helping :slightly_smiling_face: