2012-05-18 17 views
5

創建全局變量有我創建如下列表:我如何在序言

tab([(top,left),(top,middle),(top,right),(center,left),(center,middle), 
    (center,right),(bottom,left),(bottom,middle),(bottom,right)]). 

我想創建一個全局變量AllPosition這是一個標籤。所以我做了以下工作:

tab(AllPos). 

是這樣嗎?

然後,我不得不按照下面的問題: 我有一個函數,接收標籤中的一對。我想刪除。所以我這樣做:

place(Line, Column, Tab) :- 
AllPos \== [_,_] /*while AllPos isn't empty - not sur if this is done this way*/ -> (member((Line,Column), AllPos) -> (erase(AllPos, (Line,Column), AllPos)). 

其中erase(List, Element, NewList)從列表中刪除元素元素,並創建一個新的列表NewList等於名單,但沒有元素。功能membererase正在工作。

事情是......正如你可能已經注意到我在任何地方都使用AllPos。這是因爲我想要修改它,以便稍後(在刪除某些元素之後)在另一個函數中使用它。我的邏輯正確嗎?我能否在其他功能中使用修改過的AllPos? 謝謝

+0

請同時查看關於如何[**避免全局變量**]的問題和答案(http://stackoverflow.com/questions/19005042/how-to-avoid-using-assert-and-retractall-in -prolog-to-implement -all-global-or-state)在Prolog中。 – mat

回答

0

簡而言之:不,您的邏輯不正確。你的代碼存在各種小問題和錯誤,但更大的問題是基本前提。這聽起來好像你在以錯誤的方式思考問題。一般來說,如果你想在Prolog程序中更新全局狀態,你需要重新考慮你的設計。狀態更多地通過謂詞的參數來進行,所以我不希望將統一在place/4的主體中,而是預期當前的一組Tabs作爲參數被傳入。 如果你的確實是想更新你的程序的全局狀態,那麼你需要看看assertretract謂詞。

一些具體問題:

tab(AllPos). 

這個聲明在頭部未綁定變量的謂詞。它或多或少沒有意義(你可以閱讀的是「tab對某些事物是真實的,但我們沒有關於它是什麼的信息」)。

AllPos \== [_,_] 

此使用的AllPos是在不同的範圍tab/1,從在變量名共享相同的字符序列,從而開,的AllPos兩種用法沒有關係的。

1

增加伊恩的回答是:

通常使用的斷言/收縮緩慢。許多序言實現有可變的全局變量更有效的方式(例如支票SWI-序言的lib

現在,如果你想要,可以編碼幾乎就像你做了一個不變全局變量; 你將「聲明」作爲myvar(42).,但使用它,你將不得不這樣做:再次

foo:- 
    myvar(Var), 
    do_something(Var). 

,使用可變全局變量是不是真的建議,並可能導致非常,非常糟糕,難以檢測的bug由於回溯。

+0

[此答案中的鏈接](http://www.swi-prolog.org/pldoc/doc_for?object=section%282,%276.3%27,swi%28%27/doc/Manual/gvar.html% 27%29%29)似乎被打破。 –

+0

@安德森綠歡呼,修好! –

4

在SWI-Prolog中,您可以使用:b_setval(name, value)b_getval(name, value)。如果你不想在回溯的情況下改變數值,你可以使用:nb_setval(name, value)nb_getval(name, value)

因此,舉例來說,如果你有一個程序,你要檢查它通過一定的路徑如何經常去,你可以使用:

recursive(100). 
recursive(X) :- add, Y is X + 1, recursive(Y). 

add :- nb_getval(counter, C), CNew is C + 1, nb_setval(counter, CNew). 

testRecursion 
:- 
    % Set counter to zero 
    nb_setval(counter, 0), 

    % Run some code with 'add' 
    recursive(0), !, 

    % Print the results 
    nb_getval(counter, CounterValue), 
    write('Steps: '), writeln(CounterValue). 

這有利於一些實驗情況,但一般你會想要避免Prolog中的全局變量,因爲Prolog意味着邏輯編程。