我创建的列表如下:
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。功能member
和erase
都有效。
事情是......你可能已经注意到我到处都使用AllPos
。这是因为我想,我想修改它,以便我可以在以后使用它(在从中移除一些元素之后),在另一个函数中。我的逻辑是对的吗?我能在其他功能中使用修改过的AllPos吗?
感谢
答案 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
的集合作为参数传递。
如果确实想要更新程序的全局状态,那么您需要查看assert
和retract
谓词。
一些具体要点:
tab(AllPos).
这声明了一个带有未绑定变量的谓词。它或多或少毫无意义(你可以读到的是“tab
对于某些事情是正确的,但我们没有关于它是什么的信息”。
AllPos \== [_,_]
AllPos
的使用与tab/1
的范围不同,因此除了在变量名中共享相同的字符序列外,AllPos
的两种用法在所有