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

问题描述 投票:1回答:1
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,但我无法弄清楚我错在哪里。有什么指针吗?

prolog swi-prolog prolog-toplevel
1个回答
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统一,(引用相同的位置),并且B位置的界限值是2,这也是BAB的相同值。统一。


然而,在您的具体示例中,由于MaxMin从未统一,因此它只是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.

可能是SWI-Prolog保留了一个显示值表,并且它注意到MaxMin都具有相同的值,因此以这种方式显示它们,但我不想花时间挖掘code找到细节。


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

我不会用Reflection这个词来形容它。


一些代码测试用例。我曾经确保你的代码工作以防万一你有一个错误并忘了询问它。

:- 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).

示例运行

?- run_tests.
% PL-Unit: maxmin_tests ........ done
% All 8 tests passed
true.
© www.soinside.com 2019 - 2024. All rights reserved.