你的問題本質上是=:=/2
是測試,而不是建立綁定,但is/2
仍然沒有真正做你想做的。例如,儘管2 is 1 + 1
爲真,2 is X+1
將不會導致X
被綁定到1,因爲is/2
預計在左側只有一個變量或值,而在右側有一個表達式,並且它不像「關係」那樣運行Prolog的其餘部分。如果你想要這樣的算術,你應該檢查出clpfd
;考慮到它增加的複雜性是對事情是如何發生的一個很好的解釋。
幸運的是,您不需要全部算術來解決您的問題。該succ/2
內建將不正是你所需要的,和獎金,你會得到一個在線解決方案:
inc(X, Y) :- maplist(succ, X, Y).
在使用中:
?- inc([1,2,3], [2,3,4]).
true.
?- inc([1,2,3], X).
X = [2, 3, 4].
?- inc(X, [1,2,3]).
X = [0, 1, 2].
如果使用succ/2
代替=:=/2
你的代碼也能正常工作:
inc([], []).
inc([X|XS],[Y|YS]) :-
succ(X, Y),
inc(XS,YS).
這一定是您懷疑的「簡單修復」。 :)
我不確定@mbratch指的是關於一個謂詞有「太多變量」。我懷疑這是對Prolog的一個誤解,也許是其他語言的功能可以返回一個值或某物的擱置。這裏沒有技術限制;謂詞可以採取儘可能多的理由或非理性的論點,並儘可能多地綁定你想要的;限制因素是你的創造力。
同樣,我不認爲「不對稱」在這裏是一個有意義的概念。定義僅具有單一實例化模式的謂詞是非常正常的,但是對於實例化而言很靈活的謂詞也是正常的和可取的,因爲謂詞可以提前知道未來可能需要什麼用途。您可能會認爲,破壞信息的實例化模式可能會排除反例化模式,但實際上,您經常可以將其轉化爲生成器。
舉一個陳腐的例子,append/3
的名字似乎暗示着這個模式:
?- append([1,2], [3,4], X).
X = [1,2,3,4]
這是一個非常好的使用,但這樣是:
?- append(X, Y, [1,2,3,4]).
這是一個不確定性實例化模式並將產生五種解決方案:
X = [], Y = [1,2,3,4]
X = [1], Y = [2,3,4]
X = [1,2], Y = [3,4]
X = [1,2,3], Y = [4]
X = [1,2,3,4], Y = []
這似乎站在co對一些@ mbratch的想法進行了部署,但在append/3
的通常定義中沒有對地面/非地面進行明確測試,因爲它不是必需的,同樣對於第二種調用模式,您從一個輸入中獲得兩個「返回值」。 SWI source:
append([], L, L).
append([H|T], L, [H|R]) :-
append(T, L, R).
編輯:負數。我忘記succ/2
只在正整數上定義。我們可以申請@ mbratch的技術,仍然可以得到具有所需性能的漂亮的解決方案:
isucc(X, Y) :- var(X), X is Y-1.
isucc(X, Y) :- Y is X+1.
inc(X, Y) :- maplist(isucc, X, Y).
在行動:
?- inc(X, [-1,2]).
X = [-2, 1] ;
false.
編輯:使用CLP(FD)(通過@mat):
fdsucc(X,Y) :- Y #= X + 1.
inc(X, Y) :- maplist(fdsucc, X, Y).
此產生,即使是最普通的查詢:
?- inc(X, Y).
X = Y, Y = [] ;
X = [_G467],
Y = [_G476],
_G467+1#=_G476 ;
X = [_G610, _G613],
Y = [_G622, _G625],
_G610+1#=_G622,
_G613+1#=_G625 ;
X = [_G753, _G756, _G759],
Y = [_G768, _G771, _G774],
_G753+1#=_G768,
_G756+1#=_G771,
_G759+1#=_G774
...
這個問題的實用性值得懷疑,但可能是因爲您使用了clp(fd),您最終會施加其他約束並獲得一些有用的結果。
': - Y是X + 1,...' – CapelliC
@CapelliC只能解決一個方向。 –
@DanielLyons:我知道,只是建議(恕我直言)更簡單的更正。 BTW succ/2比算術慢兩倍。 – CapelliC