Question

In the process of learning Prolog I'm making simple program which given some thing is able to tell what is on the left / right / above / below of that thing. Code is this:

% left_(LeftThing, ToThing)
left_(bicycle, camera).
left_(pencil, clock).
left_(clock, butterfly).
left_(butterfly, fish).

% above_(AboveThing, ToThing)
above_(bicycle, pencil).
above_(camera,  butterfly).

right(X, Y) :-
  left_(Y, X);
  X = (empty).

below(X, Y) :-
  above_(Y, X);
  X = (empty).

left(X, Y) :-
  left_(X, Y);
  X = (empty).

above(X, Y) :-
  above_(X, Y);
  X = (empty).

position(Thing, Left, Right, Above, Below) :-
    left(Left,  Thing),
   right(Right, Thing),
   above(Above, Thing),
   below(Below, Thing), !.

Now when I ask for :

?- position(clock, Left, Right, Above, Below).

I get an answer:

Left = pencil,
Right = butterfly,
Above = Below, Below = empty.

While this is perfectly correct answer, I would like Prolog to make full substitutions and give an output in standard way:

Left = pencil,
Right = butterfly,
Above = empty,
Below = empty.

Is there a way to force Prolog doing such substitutions in output without cluttering a lot with program facts and rules ? (err... maybe there is some results formatting option in SWI-Prolog configuration. If not - how to achieve this with minimal code changes ?)

Was it helpful?

Solution

Prolog returns a most general unifier as a solution when it finds one. Here it is a perfectly standard one and I didn't find any flag to change this behavior (I might have missed one though, maybe a toplevel_print_options custom predicate or something).

That being said, you could roll your own print predicate if you want a prettyprint. It'd allow you to clean your database btw, because here you represent extra stuff from the original problem only to be able to return empty, which isn't good from a conception point of view. My take would be:

% left(LeftThing, ToThing)
left(  bicycle,   camera).
left(  pencil,    clock).
left(  clock,     butterfly).
left(  butterfly, fish).

% above(AboveThing, ToThing)
above( bicycle,   pencil).
above( camera,    butterfly).

right(X, Y) :-
    left(Y, X).

below(X, Y) :-
    above(Y, X).

print_custom(Y, Pred) :-
    (   call(Pred, X, Y)
     -> true
      ; X = empty),
    format('~w = ~w,~n', [Pred, X]).


position(Thing) :-
    maplist( print_custom(Thing),
             [left, right, above, below] ).

Test:

?- position(clock).
left = pencil,
right = butterfly,
above = empty,
below = empty,
true.

OTHER TIPS

I can't find a flag controlling this behaviour, and internally (see boot/toplevel.pl) join_same_bindings/2 is called unconditionally.

There is an undocumented predicate print_toplevel_variables/0, but the output is not ordered, and contains 'historical' variables unrelated to last query:

?- position(clock, Left, Right, Above, Below).
Left = pencil,
Right = butterfly,
Above = Below, Below = empty.

?- print_toplevel_variables.
$Below =    empty
$Above =    empty
$Right =    butterfly
$Left =     pencil
$X =        false
$T =        position(clock,pencil,butterfly,empty,empty)
$Y =        1
false.
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top