[英]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 可以將兩個自由變量統一到一起,例如A
和B
,當其中一個成為綁定時,另一個也同時綁定,因為它們之前是統一的。
雖然不完全准確,但另一種思考方式是作為指針。
如果開始時一個指針指向A
,另一個指針指向B
,它們是不同的位置,后來發現A
和B
是統一的,那么指向A
和B
的指針將被調整為現在指向同一位置。 然而,它們指向的位置仍然是一個未綁定的位置,因為A
或B
都沒有值。 當A
或B
綁定到一個值時,它們都會同時綁定,因為指針指向相同的位置。
下面是一些演示細節的測試代碼。
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
代表兩個不同的未綁定變量。
請注意, A
和B
在內部引用不同。
接下來代碼執行A = B
然后
在第 3 行,變量A
在內部被引用為_480
在第 4 行中,變量B
在內部被引用為_480
請注意,現在A
和B
在內部引用相同的內容: _480
。
接下來代碼執行A = 5
在第 5 行中,變量A
內部引用了_480
,它現在與值5
綁定。
在第 6 行,變量B
內部引用了_480
,它現在與值5
綁定。
發生這種情況時,不是兩個單獨的綁定,而是一個綁定到一個位置,由於統一,因此引用了同一位置,兩個變量通過一個動作綁定到一個值。
因此,當您看到B = A, A = 2.
,可能意味着B
和A
是統一的(引用相同的位置),並且B
的位置中的綁定值為2
,這也是相同的綁定值對於B
因為A
和B
是統一的。
但是,在您的具體示例中,由於Max
和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.
可能是 SWI-Prolog 保留了一個顯示值表,並且它注意到Max
和Min
具有相同的值,因此以這種方式顯示它們,但我不想花時間深入研究代碼找到細節。
這是我不知道的 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.