如何在prolog中创建全局变量

时间:2012-05-18 15:00:13

标签: list variables prolog global reusability

我创建的列表如下:

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)从List中删除元素Element并创建一个新列表NewList等于List但没有Element。功能membererase都有效。

事情是......你可能已经注意到我到处都使用AllPos。这是因为我想,我想修改它,以便我可以在以后使用它(在从中移除一些元素之后),在另一个函数中。我的逻辑是对的吗?我能在其他功能中使用修改过的AllPos吗? 感谢

3 个答案:

答案 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意味着用逻辑编程。

答案 1 :(得分:1)

加入伊恩的回答:

通常使用assert / retract很慢。许多prolog实现为可变全局变量提供了更有效的方法(例如检查swi-prolog' s lib

现在,如果你想要一个不可变的全局变量,它可以像你一样编码; 你会"宣布"它为myvar(42).但要使用它你必须这样做:

foo:-
   myvar(Var),
   do_something(Var).
再次,使用可变全局变量并没有真正建议,并且可能导致非常非常糟糕并且难以检测由于回溯导致的错误。

答案 2 :(得分:0)

简而言之:不,你的逻辑不正确。您的代码存在各种小问题和错误,但更大的问题是基本前提。听起来好像你正在以错误的方式思考这个问题。通常,如果您尝试在Prolog程序中更新全局状态,则需要重新考虑您的设计。状态通常由谓词的参数携带,因此我不希望在AllTabs的主体中统一place/4,而是希望将当前Tabs的集合作为参数传递。 如果确实想要更新程序的全局状态,那么您需要查看assertretract谓词。

一些具体要点:

tab(AllPos).

这声明了一个带有未绑定变量的谓词。它或多或少毫无意义(你可以读到的是“tab对于某些事情是正确的,但我们没有关于它是什么的信息”。

AllPos \== [_,_]

AllPos的使用与tab/1的范围不同,因此除了在变量名中共享相同的字符序列外,AllPos的两种用法在所有