2

I have the next code in a file called "testing.pl":

fact(1).
fact(2).
fact(3).

funcA(X) :- funcB(X).

funcB(X) :- fact(X).

testing :- funcA(_X).

Then, in SWI-Prolog interpreter I query funcA(X). and the output is:

X = 1 ;
X = 2 ;
X = 3.

But, whenever I query testing. the output is:

true ;
true ;
true.

So, my questions is:

How can I use the conclusion of a rule as a premise of another rule (funcA(X) at the right of testing), but having the same effect as if I query that premise (funcA(X))?

In the example above, I would like to write testing. at some point of my "testing.pl" file and to get the funcA(X) to do the same like when I query with the interpreter, so funcB(X) will check for all values that X can take from fact(N) and return it.

My desire result would be to write testing. and to get on screen:

X = 1 ;
X = 2 ;
X = 3.

Thanks.

false
  • 10,264
  • 13
  • 101
  • 209
Haddex
  • 38
  • 1
  • 8
  • 2
    If you want `testing.` to result in `X = 1, ...` then you need to have `X` be an argument to `testing`. So, `testing(X) :- funcA(X).` (which doesn't seem to add any purpose). Alternatively, and less preferably, you could write the results: `testing :- funcA(X), write('X = '), write(X), nl.` – lurker Apr 13 '17 at 12:58

1 Answers1

3

You can manually print anything on the terminal, using for example predicates like portray_clause/1, format/2 etc.

The only additional piece you need is a way to force backtracking over all answers. One way to do it is using false/0.

So, in your case, you can write for example:

testing :-
        funcA(X),
        format("X = ~q ;~n", [X]),
        false.

And now invoking testing/0 yields, without any further interaction:

?- testing.
X = 1 ;
X = 2 ;
X = 3 ;

In addition, the predicates now fails, so you also get false/0 if you use it interactively (from the toplevel), but not if you invoke testing from the shell via swipl -g testing ....

Also take a look at the important variable_names/1 option that is available to use the intended variable names.

I lave tailoring this output to your exact use case as an exercise. Ideally, the output should be a proper Prolog term, so that you can actually test it easily by reading it with read/1 and comparing it to a reference result.

Community
  • 1
  • 1
mat
  • 40,498
  • 3
  • 51
  • 78
  • Really nice answer, but the problem I presented was just an abstraction of my real code, which unfortunately is interactive (is in a menu loop). So it gets stuck at the false. Anyway, is the answer to what I asked, thank you very much. – Haddex Apr 13 '17 at 13:34
  • 2
    You are welcome. Let me also address your actual code: One clean way out is to first *separate* the impurities (i.e., input/output) from the actual program logic. For example, to represent a menu in a **pure** way, use a predicate like `menu0_key_menu/3`, *relating* one state of the menu to a new state of the menu, depending on which `Key` is pressed. This way, you can actually *test* how your menu behaves by reasoning about this pure relation, "simulating" the actual key presses by simply providing them in goals, like `menu0_key_menu(M0, q, exit).`, which should *succeed* (for example). – mat Apr 13 '17 at 13:43