簡體   English   中英

為什么 Prolog 將一個自由變量統一到另一個自由變量?

[英]Why is Prolog unifying a free variable to another free?

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 Exit: (8) maxmin([2], 2, 2) ? creep對我來說看起來非常好。 這只會在我有 1 的列表時發生。

我顯然不理解 Prolog,但我一生都無法弄清楚我錯在哪里。 任何指針?

它怎么可能將一個免費分配給另一個免費?

你對assigning這個詞的使用告訴我們一個關於你如何看待 Prolog 的秘密。 當您在 Prolog 中看到=時,這不是賦值,而是統一,請參閱: =/2 Prolog 通過統一或更具體的句法統一工作

如果 Prolog 可以將兩個自由變量統一到一起,例如AB ,當其中一個成為綁定時,另一個也同時綁定,因為它們之前是統一的。

雖然不完全准確,但另一種思考方式是作為指針。

如果開始時一個指針指向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 ,這也是相同的綁定值對於B因為AB是統一的。


但是,在您的具體示例中,由於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具有相同的值,因此以這種方式顯示它們,但我不想花時間深入研究代碼找到細節。


這是我不知道的 Prolog 中的一些反射內容嗎?

我不會用反射這個詞來描述它。


您的代碼的一些測試用例。 我曾經確保您的代碼正常工作,以防您遇到錯誤而忘記詢問它。

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM