Reputation: 11267
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 ?)
Upvotes: 2
Views: 157
Reputation: 60004
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.
Upvotes: 2
Reputation: 7493
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.
Upvotes: 3