1

I'm trying to precompute some stuff and save the results as facts at the beginning of my program: (simplified code)

:- dynamic cost/2.
%recipe(Id,Cost)
recipe(1,20).
recipe(2,40).

assert_all :- recipe(Id,Cost), assert(cost(Id,Cost)).

But only the first result, cost(1,20) gets asserted when I consult the file in SICStus Prolog:

| ?- assert_all.
yes
| ?- cost(Id,Cost).
Id = 1,
Cost = 20 ? ;
no
| ?

However, when I input the right-hand side of assert_all in the SICStus prolog console directly, both cost/2 facts are there.

| ?- recipe(Id,Cost), assert(cost(Id,Cost)).
Id = 1,
Cost = 20 ? ;
Id = 2,
Cost = 40 ? ;
no
| ?- cost(Id,Cost).                         
Id = 1,
Cost = 20 ? ;
Id = 2,
Cost = 40 ? ;
no

I find this behavior very confusing, what's going on?

Juraj
  • 99
  • 7
  • Try using asserta to save your results at the beginning: http://www.learnprolognow.org/lpnpage.php?pagetype=html&pageid=lpn-htmlse48 – s.dallapalma May 18 '16 at 10:55

1 Answers1

2

Put a fail/0 in your original clause and add another clause that just succeeds:

assert_all:- 
  recipe(Id,Cost), 
  assert(cost(Id,Cost)),
  fail.
assert_all.

Whats going on is that your procedure as you wrote it asserted the first cost for a recipe and left a choice point. Upon backtracking it would eventually assert the other facts (if it backtracks, which is what is happening when you ask for more alternatives by pressing ; in the Sicstus console).

The fail driven loop of this answer just backtracks every solution for recipe/2 and asserts its cost. Then the second clause just succeeds.

gusbro
  • 22,357
  • 35
  • 46