2

在学习 Prolog 的过程中,我正在制作简单的程序,给定一些东西能够分辨出那个东西的左/右/上/下是什么。代码是这样的:

% 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), !.

现在当我要求:

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

我得到一个答案:

左 = 铅笔,
右 = 蝴蝶,
上 = 下,下 = 空。

虽然这是完全正确的答案,但我希望 Prolog 进行完全替换并以标准方式给出输出:

左 = 铅笔,
右 = 蝴蝶,
以上=空,
下面=空。

有没有办法强制 Prolog 在输出中进行这样的替换,而不会使程序事实和规则混乱很多?(错误......也许在 SWI-Prolog 配置中有一些结果格式化选项。如果没有 - 如何通过最少的代码更改来实现这一点?)

4

2 回答 2

3

Prolog 找到一个最通用的统一器作为解决方案。这是一个完美的标准,我没有找到任何标志来改变这种行为(虽然我可能错过了一个,也许是一个toplevel_print_options自定义谓词或其他东西)。

话虽如此,如果你想要一个漂亮的打印,你可以滚动你自己的打印谓词。顺便说一句,它可以让你清理你的数据库,因为在这里你代表了原始问题中的额外内容,只能返回empty,从概念的角度来看,这并不好。我的看法是:

% 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] ).

测试:

?- position(clock).
left = pencil,
right = butterfly,
above = empty,
below = empty,
true.
于 2012-09-06T14:37:16.697 回答
2

我找不到控制这种行为的标志,并且在内部(参见 boot/toplevel.pl)无条件调用 join_same_bindings/2。

有一个未记录的谓词 print_toplevel_variables/0,但输出没有排序,并且包含与上次查询无关的“历史”变量:

?- 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.
于 2012-09-06T15:03:14.293 回答