5

次のように作成するリストがあります。

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

タブであるグローバル変数 AllPosition を作成したいと考えています。だから私は次のことをしました:

tab(AllPos).

これは正しいですか?

次に、問題に従う必要があります。タブでペアの1つを受け取る関数があります。削除したいもの。だから私はこれをしました:

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)、要素 Element を List から消去し、List と等しいが Element を含まない新しいリスト NewList を作成します。member機能と機能の両方が機能しeraseています。

問題は... お気づきかもしれませんが、私はAllPosどこでも使用しています。それは私がしたいので、それを変更して、後で(いくつかの要素を削除した後)別の関数で使用できるようにしたいからです。私の論理は正しいですか?変更した AllPos を別の関数で使用できますか? ありがとう

4

3 に答える 3

5

b_setval(name, value)SWI-Prolog では、 とを使用できます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 ではグローバル変数を避けたいと思うでしょう。

于 2012-12-19T16:06:24.493 に答える
2

イアンの答えに追加:

一般に、アサート/リトラクトの使用は低速です。多くのプロローグの実装には、変更可能なグローバル変数のためのより効率的な方法があります (たとえば、swi-prolog のlibを確認してください) 。

今、ほとんど同じようにエンコードできる不変のグローバル変数が必要な場合; あなたはそれを「宣言」しますmyvar(42).が、それを使用するにはこれを行う必要があります:

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

繰り返しますが、変更可能なグローバル変数を使用することは実際には推奨されておらず、バックトラッキングが原因でバグを検出するのが非常に困難で困難になる可能性があります。

于 2012-05-18T16:37:54.620 に答える
1

簡単に言えば、いいえ、あなたの論理は正しくありません。コードにはさまざまな小さな問題やバグがありますが、より大きな問題は基本的な前提です。問題を間違った方法で考えているように聞こえます。一般に、Prolog プログラムでグローバル状態を更新しようとしている場合は、設計を再考する必要があります。AllTabs状態は通常、述語への引数によって運ばれるため、 の本体で統一するのではなく、 current のセットが引数として渡されることplace/4を期待していました。プログラムのグローバルな状態を本当に更新したいTabs場合は、述語と述語を調べる必要があります。assertretract

いくつかの特定のポイント:

tab(AllPos).

これは、ヘッドにバインドされていない変数を持つ述語を宣言します。それは多かれ少なかれ無意味です(「それはtab何かの真である場合ですが、それが真であるという情報はありません」で読むことができます)。

AllPos \== [_,_]

この の使用はAllPosとはスコープが異なるtab/1ため、変数名で同じ文字列を共有することを除けば、 の 2 つの使用にAllPosはまったく関係がありません。

于 2012-05-18T15:16:13.510 に答える