Prologプログラミングの中で常に留意するべきものとして副作用がある。副作用を考える場合、それではPrologに於いて作用とは何かを示す必要があるだろう。これは、目標(副目標)の実行に伴う真偽値のことである。Prologが質問に対して返すものは真か偽のみである。これ以外に処理系の動作に影響のある変化が起こった時、それを副作用という。ただし真か偽に決まるための論理変数の単一化による代入は副作用ではないとする。大域変数など、破壊代入を伴う機能は提供されないというのがPrologの原則であるが、大域変数を用意してプログラマに手続き言語的な便宜を供している処理系もある。また、次期ISO標準規格の議論の中でも大域変数の使用が提案されている。しかし、以下の副作用についての解説では、大域変数は利用できないこととして話を進める。組込述語もなく、もちろんカットもなく、ユーザが定義した述語だけで実行される純Prologに於いては、副作用は生じない。述語論理のイメージに近い純Prologはこの系の規範となる。したがってPrologプログラマにとって、この純Prologからの逸脱を象徴する副作用は厄介な存在である。副作用を大別すると、・ 述語定義に変更を与えるもの。・ 入出力に伴うもの。・ 処理系が管理するプロパティ情報の参照や変更。がある。最初に述語定義に変更を与えたため起こる副作用の例を示そう。年齢合計/1は年齢/2を関係データベースと見做し、この第二引数を全て合計したいという述語である。年齢(尾崎,65).年齢(山下,37).:- dynamic(一時年齢合計/1).年齢合計(_年齢合計) :-    assertz(一時年齢合計(0)),    年齢(_,_年齢),    retract(一時年齢合計(_年齢合計_1)),    _年齢合計_2 is _年齢合計_1 + _年齢,    assertz(一時年齢合計(_年齢合計_2)),    fail.年齢合計(_年齢合計) :-    retract(一時年齢合計(_年齢合計)).これは強制的な失敗とバックトラックを使って述語定義とその解消を繰り返して、年齢を合計(集約)するものだ。見れば分るとおりどの言語のそれにも増しても冗長なコードである。このようなコードだけは決して書きたくないとほとんどのPrologプログラマは思っていて、実際にこのタイプの述語定義が書かれることはない。それでは、どのように集約プログラムを書くのだろうか。この年齢合計は、以下のように定義するのが普通である。年齢合計(_年齢合計) :-    findall(_年齢,年齢(_,_年齢),_年齢のリスト),    加算(_年齢のリスト,_年齢合計).加算([],0).加算([_年齢|R],_年齢合計) :-    加算(R,_年齢合計_2),    _年齢合計 is _年齢 + _年齢合計_2.findall/3で一旦リストに年齢を取り出した上で、これを再帰的に加算する。洗練された表現であるし、一般にはこれで良しとする。しかし、実はfindall/3自体に上記のようなassert/retractのからくりが含まれている。findallは第二引数が真になった場合、第一引数によって指定された項を収集するものだが、その収集する場が乃ち副作用であるという関係になる。findallが組込述語になっていて、C言語などでその記述がされている場合は、普通に破壊代入を使ってこれを実現していると見て間違いない。findall/3を利用しているプログラマは意識していないかもしれないが、findall/3にはこのような副作用が含まれ、しかし、それが利用者には隠蔽されているのである。副作用という観点から少し外れるが、Prologと関係データベースの関係にもう一度触れる。Prologの述語の定義節はそれぞれが論理的に全く独立で何の連関もない。連関がないものを集約できるわけもない。述語の節定義を関係データベースと見做した年齢/2であるが、そのことの本質的な無理が露呈していると考えることもできる。findall/3は連関がないものを、順序性を持つリストに組み立てることによって連関を付けたのである。述語を関係データベースと見做した場合、更新や削除は当然副作用である。氏名をキーとした年齢の更新(_氏名,_更新する年齢) :-    retract(年齢(_氏名,_)),    assertz(年齢(_氏名,_更新する年齢)).これは、先ほどの一時年齢合計/2の場合とは異なり、確信犯的に副作用を使用していると云って良い。述語定義に変更を与える副作用としては、組込述語のasserta/1,assertz/1,retract/1などがあり、これが実行された前と後では、同じ目標を与えたとしても真偽値に変化があったり、引数の単一化の決まり方に変化が起こり、プログラマの予期に反する結果が起こる可能性がある。また上記の例のように冗長な表現になる。それらがこのタイプの副作用が嫌われる理由である。入出力に伴う副作用は、組込述語の read,get,get_char,write,put,put_charなどの実行でおこり、オペレーションシステムに管理されるファイル指示子が変化してしまったり、画面に表示、用紙に印字されるなど、元に戻すことが極めて難しい変化が起こる。キーボードからの入力も副作用である。この中でもファイルの指示子などは一度進んでしまうと、簡単には元に戻することができない場合もあり、再実行を指向するバックトラックによる制御と整合しなくなることも多い。入出力に伴う副作用の例を示す。奇数が入力されるまで整数をリストに得る([]) :-    read(_奇数),    1 is _奇数 mod 2.奇数が入力されるまで整数をリストに得る([_整数|R]) :-    read(_整数),    奇数が入力されるまで整数をリストに得る(R).read/1で整数を得る。奇数なら終了するのだが、偶数だと第一節は失敗する。ここでは、_奇数に偶数が入力されて偽となったのである。だからといってファイルの指示子が元に戻ることはない。第二節に移行して、read(_整数) が実行されると、既に読み込んだ情報の次の指示子に基づいて入力が得られる。この結果、第一節で読み込んた偶数はリストに取得されることなく飛ばされてしまう。ここでは最も単純な例を挙げたが、ほとんどの入出力部分には多かれ少なかれ、このような危険が潜んでいる。上記副作用プログラムの適切な述語定義を示す。これでread/1が一箇所に絞られたから読み飛ばしの危険がなくなる。奇数が入力されるまで整数をリストに得る(_偶数リスト) :-    read(_整数),    奇数が入力されるまで整数をリストに得る(_整数,_偶数リスト).奇数が入力されるまで整数をリストに得る(_奇数,[]) :- 奇数(_奇数),!.奇数が入力されるまで整数をリストに得る(_偶数,[_偶数|R]) :-    奇数が入力されるまで整数をリストに得る(R).奇数(_奇数) :- \+(0 is _奇数 mod 2).処理系が管理するプロパティ等の情報もほとんどの場合副作用である。処理系の挙動を制御するために使うものが多いが、事実上の大域変数の破壊代入である。目標(質問)の実行から停止までの間に、度々変更するような使い方をするならば、プログラムの分かりやすさを損なう。一般にこのタイプの副作用があまり問題にならないのは、設定の変更が滅多に起こるものではないからである。使い方が難しいこともあり、あまり頻繁に使用されるというものではない。しかし、prolog_propertyといった述語で管理される情報は増える傾向にある。述語定義に変更を加えるもの、入出力に伴うもの、処理系の管理するプロパティの書き換え。どれを取っても、副作用が生じると論理的な必然だけでは理解することが済まなくなり、コードの見通しが悪くなる。現在のPrologの規格では、手続き型のほとんどの言語とは異なり、大域変数などの破壊代入(既に保持されている値を上書きする形で更新される代入)は基本的にできないことになっている。もちろん破壊代入が許される場合はここを舞台に起こる変化は全て副作用である。いつ記述されたか必ずしも明らかにできない変数に代入された値が、後に利用されることはプログラムの理解を著しく損ねる。Prologでは原則、目標の引数に現れた値は全ての解を得て完了した時点で、二度とこれを利用出来なくなる。多くの場合情報を積んであったスタックがPOPされてしまう。実務的なプログラムでは、Prologの単一化と導出、バックトラックを使って記述されるロジックを基礎に、その間に、表示を代表とする副作用述語を挿入記述することによって、実用的な機能を実現している。定理証明やデータベースの参照に於いては、このような副作用の挿入記述なしに、インタプリタ上で解を確認したり、真偽値を得ることだけで、目的を達成できる。しかし、他のほとんどのプログラムでは、必要な箇所で、適切な時期に、整理したデータの開示を要求される。このような表示はPrologに於いても、ほとんど全てが副作用であって、「Prologプログラムとはロジックの上に副作用をちりばめることだ」と言っても過言ではない。現実に、データベースの更新の例を挙げて述べた表現のように、「確信犯的」に副作用述語が利用されている。そのこともまた事実であるが、Prologコミュニティではプログラムコードの副作用を極力少なく書くことが強く奨励されている。多くのプログラマが副作用に注意し、これを減らす努力をするし、大域変数が許された処理系の利用者も最小限にしかこれを使わない。ほとんどのPrologプログラムには、破壊代入に見られるような一命令で与えられる変化で全体の制御が変わってしまうという部分はない。これは、副作用として現れた変化を利用することはしないという姿勢、意識がPrologプログラマの間で貫かれ、共有されているからである。Prologの制御の焦点は、単に述語の引数の単一化にある。副作用の存在が、実際のPrologプログラムの中で、単一化を注視することだけでプログラムを理解することの妨げになっている例を見ることは、ほとんどない。