为什么Prolog将一个自由变量统一为另一个自由变量?

时间:2019-03-07 02:28:32

标签: prolog swi-prolog prolog-toplevel

maxmin([X|L], Max, Min) :-
    maxmin(L, X, X, Max, Min),
    !.

maxmin([], CurrentMax, CurrentMin, Max, Min) :-
    Max is CurrentMax,
    Min is CurrentMin,
    !.
maxmin([X|L], CurrentMax, CurrentMin, Max, Min) :-
    CurrentMax2 is max(X, CurrentMax),
    CurrentMin2 is min(X, CurrentMin),
    maxmin(L, CurrentMax2, CurrentMin2, Max, Min).

执行查询?- maxmin([2],Max,Min).后,它将返回Max = Min, Min = 2.

为什么?我对此有几种变化,但似乎都没有。它如何可能将一个自由分配给另一个自由?这是我不了解的Prolog中的一些反思性内容吗?

跟踪也没有显示任何特别有趣的内容。即,它从Exit: (8) maxmin([2], 2, 2) ? creep退出,这对我来说似乎很好。只有当我的列表为1时,才会发生这种情况。

我显然不了解Prolog,但是我无法弄清楚我的生活中哪里错了。有指针吗?

1 个答案:

答案 0 :(得分:3)

  

它有可能将一个空闲空间分配给另一个空闲空间吗?

您对assigning一词的使用告诉了我们一个有关Prolog的秘密。当您在Prolog中看到=时,这不是分配而是统一,请参阅:=/2。 Prolog通过统一或更具体地说syntactic unification来工作。

如果Prolog可以将两个free variables合并在一起,例如AB,并且当其中一个变为bound时,另一个也同时绑定因为它们以前是统一的。

虽然不是完全准确,但另一种思考方式是指针。

如果从一个指向A的指针和另一个指向B的指针开始,这两个指针在不同的位置,而后者又发现AB是统一的,指向AB的指针将被调整为现在指向相同的位置。但是,它们指向的位置仍然是未绑定的位置,因为AB都没有值。将AB绑定到一个值时,由于指针指向相同的位置,它们都将同时绑定。

这是一些测试代码,演示了细节。

test_01 :-
    format('A: ~w~n',[A]),
    format('B: ~w~n',[B]),
    A = B,
    format('A: ~w~n',[A]),
    format('B: ~w~n',[B]),
    A = 5,
    format('A: ~w~n',[A]),
    format('B: ~w~n',[B]).

运行此命令将返回以下内容。我是在事后手动添加评论的。

?- test_01.
A: _480      % Line 1
B: _486      % Line 2
A: _480      % line 3
B: _480      % line 4
A: 5         % Line 5
B: 5         % Line 6
true.

在第1行中,变量A在内部被称为未绑定变量:_480
在第2行中,变量B在内部被称为未绑定变量:_486
请注意,_480_486代表两个不同的未绑定变量。
请注意,AB在内部没有引用

接下来,代码执行A = B

然后

在第3行中,变量A在内部被称为_480
在第4行中,变量B在内部被称为_480

请注意,现在AB 内部引用了相同的内容:_480

接下来,代码执行A = 5

第5行中的变量A内部引用_480,该变量现在与值5绑定。
在第6行中,变量B内部引用了_480,该变量现在与值5绑定了。

发生这种情况时,没有两个单独的绑定,而是一个绑定到一个位置,这是由于统一以及对同一位置的引用,两个变量通过一个动作绑定到一个值。

因此,当您看到B = A, A = 2.时,可能意味着BA是统一的(引用相同的位置),并且{{1 }}是B,由于2B是统一的,因此它也是A的绑定值。


但是在您的特定示例中,由于BMax从未统一,所以这只是SWI-Prolog显示它们的特殊方式。

我跟踪了您的示例,以准确了解您的注释。

Min

可能是SWI-Prolog保留了一个显示值表,并且它注意到?- leash(-all),visible(+all),trace. true. [trace] ?- maxmin([2],Max,Min). Call: (8) maxmin([2], _4408, _4410) Unify: (8) maxmin([2], _4408, _4410) Call: (9) maxmin([], 2, 2, _4408, _4410) Unify: (9) maxmin([], 2, 2, _4408, _4410) Call: (10) _4408 is 2 Exit: (10) 2 is 2 Call: (10) _4410 is 2 Exit: (10) 2 is 2 Exit: (9) maxmin([], 2, 2, 2, 2) Exit: (8) maxmin([2], 2, 2) Max = Min, Min = 2. Max都具有相同的值,所以以这种方式显示它们,但我不想花时间深入code来查找详细信息。


  

这是我不知道的Prolog中的一些反思吗?

我不会使用单词Reflection来描述它。


您的代码的一些测试用例。我曾经确保您的代码可以正常运行,以防万一您有一个错误而忘了询问它。

Min

示例运行

:- begin_tests(maxmin_tests).

maxmin_test_case([1],1,1).
maxmin_test_case([1,2],2,1).
maxmin_test_case([2,1],2,1).
maxmin_test_case([1,2,3],3,1).
maxmin_test_case([3,2,1],3,1).
maxmin_test_case([2,3,1],3,1).
maxmin_test_case([3,1,2],3,1).

test(1,[forall(maxmin_test_case(Input,Expected_max,Expected_min))]) :-
    maxmin(Input,Max,Min),
    assertion( Max == Expected_max ),
    assertion( Min == Expected_min ).

test(2,[fail]) :-
    maxmin([],_,_).

:- end_tests(maxmin_tests).