2017-03-17 64 views
1

我一直在閱讀並注意到,諸如調用的謂詞被稱爲元謂語,並且它們可以返回其他謂詞作爲結果(不知道返回是否很好地利用了單詞這裏)例如這裏:在序言中的元謂語變換

assert(call(goal, X,Y)). 

編輯:lurker打電話給我的理由,這是行不通的。

據我所知,它不應該調用謂詞函數,但是有沒有一種方法來斷言直到運行時纔會知道的謂詞?

我想爲多個事實使用相同的插入謂詞,所以assert(fact(X))不適合我的需要。我可以在運行時檢索事實的名稱,但是如何直接使用assert而不直接統一事實呢?

+1

當你說'斷言(電話(目標,X,Y))'*將工作*什麼呢。那是什麼意思以什麼方式工作?我所看到的是試圖斷言「調用(...)」會導致嘗試修改現有Prolog過程(「調用」)的錯誤。 – lurker

+0

@ lurker你對我的朋友很對,我很累,我想象我看到它的工作。如果事先不知道斷言所需的謂詞,是否有辦法斷言?我會修改我的問題。對不起 – Souza

+1

不用擔心。談到手頭的問題:謂詞只是一個*術語*對嗎?它看起來像'': - '(head,body)'。所以你可以做'assertz(': - '(Head,Body))''在運行時實例化'Head'和'Body'。你也可以把它寫成assertz((Head: - Body)),因爲':-'是一個操作符。請注意,'assertz/1'調用時'Head'和'Body'應該被隔離。 – lurker

回答

1

您應該明確使用assertz/1asserta/1assert/1assertz/1的別名,但僅限於某些Prolog系統。

召喚:

assertz(call(goal, X, Y)). 

將嘗試斷言事實與仿函數call。這就是它試圖在數據庫中斷言:

call(goal, _, _). 

由於call在Prolog中是已被定義爲一個謂語一個仿函數,它會產生一個錯誤。如果你斷言,說以下內容:

assertz(foo(goal, X, Y)). 

這將是成功的,但你會得到數據庫是這樣的:

foo(goal, _, _). 

似乎這不是很有用。換句話說,assert正在按照你的要求去做:聲明你剛纔描述的的術語,在上面的例子中,它的函子是callfoo

如果你想斷言一個實際的謂詞,你只需要使用謂詞是的術語這個事實,其函子是:-。一般謂詞可以是Head :- Body,或者是規範形式':-'(Head, Body)。只要至少在調用assertz之前實例化了至少Head,就可以聲明這種術語。

assertz(':-'(Head, Body)). 

或等價(因爲:-是運營商):

assertz((Head :- Body)). 

如果我這樣做:

Head = goal, assertz((Head :- Body)). 

我得到(使用listing/0):

:- listing. 

goal :- 
    call(_). 

不是非常有用UL認證。所以Body確實應該在進行assertz/1調用之前實例化。那麼,這是另外一個例子:

Head = double(X, Y), Body = (Y is X * 2), assertz((Head :- Body)). 

現在結果如下:

:- listing. 

double(A, B) :- 
     B is A * 2. 
+0

一如既往,很好的解釋和重點。非常感謝。 – Souza