只是補充臺現有優秀的答案...
在Prolog,你沒有想到的事情爲「功能」與參數的輸入和輸出(雖然他們行爲是那樣),而是作爲「謂詞「定義規則,並將嘗試實例化任何變量參數(未經實例化的變量),以使規則成立。這個過程可能會導致沒有解決方案,一個解決方案或許多解決方案,並且您將全部獲得。並非所有的謂詞都爲未經證實的變量的每個組合提供了這種「全部功能」,或者如果太多的變量沒有被證實,那麼提供解決方案在邏輯上就變得不切實際。在任何這些情況下決定參數的行爲,以及謂詞是否有任何解決方案,都是謂詞的邏輯,而不是任何正式的輸入或輸出聲明。
讓我們以給定的concatenate
爲例(注意我使用的是GNU Prolog)。謂詞concatenate(L1, L2, L3)
的含義是「L1與L2連接(按此順序)給出L3」,這比說「給定L1和L2提供它們在L3中的級聯」更普遍,這意味着特定的輸入和輸出。
所以,如果我進入:
concatenate([1,2], [3,4], L3).
我得到:
L3 = [1,2,3,4]
(1 ms) yes
| ?-
這意味着序言找到一個解決方案與L3
所示實例謂語。我還可以輸入:
concatenate(L1, [3,4], [1,2,3,4]).
而且我會得到:
L1 = [1,2]
(1 ms) yes
| ?-
這意味着序言找到一個解決方案與L1
所示實例謂語。同樣如果我輸入concatenate([1,2], L2, [1,2,3,4])
我會得到一個解決方案:L2 = [3,4]
。
讓我們嘗試一些更有趣:
concatenate(L1, L2, [1,2,3,4]).
的Prolog會發現這個解決方案,但我已經提供了兩個非實例變量。因此,解決方案將涉及這些可能性:
L1 = [1,2,3,4]
L2 = [] ? ;
L1 = [1,2,3]
L2 = [4] ? ;
L1 = [1,2]
L2 = [3,4] ? ;
L1 = [1]
L2 = [2,3,4] ? ;
L1 = []
L1 = [1,2,3,4] ? ;
(1 ms) yes
| ?-
現在讓我們試試這個:
concatenate([1,2], L2, L3).
我得到:
L3 = [1,2|L2]
| ?-
在這種情況下,爲L2
,因此可能性, L3
是無界的,所以序言顯示了一個通用的解決方案。
在你的例子中,concatenate(X, [2,Y], [1,1,1,2,3])
適用同樣的想法。Prolog將嘗試找到滿足條件的X
和Y
的實例,滿足條件:「與[2,Y]連接的X給出[1,1,1,2,3]」,[2,Y]是帶有第一個元素的列表2
和第二元素Y
。在這種情況下,您只有一個解決方案。
由於關於這一主題的變化,使用@DrH描述列表的概念,如果你這樣做:
concatenate(X, [2|Y], [1,1,1,2,3]).
你會得到X = [1,1,1]
和Y = [3]
。請注意,如果你這樣做:
concatenate(X, [2,Y], [1,1,1,2,3,4]).
你得到「沒有」(沒有解決),因爲Y
在此處顯示爲一個原子,而不是(因爲逗號語法)的列表。換句話說,沒有兩個元素列表看起來像[2,Y]
,當與X
的任何可能性連接時將產生[1,1,1,2,3,4]
。但是,如果你這樣做:
concatenate(X, [2|Y], [1,1,1,2,3,4]).
你會得到X = [1,1,1]
和Y = [3,4]
因爲我現在顯示未初始化Y
以列表的尾部,它本身就是一個列表,而不是隻是一個原子(使用|
語法)。
正如@WillNess指出的那樣,給定謂詞的文檔將告訴您如果讓某些變量沒有實際意義,就希望預測謂詞的行爲。一篇寫得好的序言式謂詞比起那些寫得不好或者限制較多的序言更有可能「做你期望或想要做的事」。這不會使限制性較強的謂詞「不好」,因爲它可能有一個非常有用的目的。它不會有用。在編寫自己的序言謂詞時,需要考慮這些事情。 Prolog就像Go的遊戲:一些簡單的規則,但很多有趣的可能性。