あなたはこのトレースを読むために多くの手順上のアイデア(荷物)を持っています。 Prologの目でそれを試してみましょう:
Call: (7) alter([keith, is, very, cool], _G2676) ? creep
ここで目標を再提示してください。生成された変数_G2676
の数値は無視できます。それはメモリの場所ではなく、これらの変数名を生成する方法は実装とプラットフォームによって異なります.Prologには任意のメモリ位置を読み取るメカニズムがありません。生成された変数番号はほとんどすべての意味でアクセスできません。それは単なる内部簿記です。
あなたは、おそらくこのようなクエリを発行:
?- alter([keith, is, very, cool], B).
はこのようにそれについて考えてみよう。あなたはプロローグに、「alter([keith, is, very, cool], B)
を証明し、Bが何であるか教えてください」と尋ねている。それで、それをやろうとしています。ここで何が起こった
Call: (8) change(keith, _G2756) ? creep
? Prologはあなたのクエリを見て、あなたがalter/2
を使っているのを見ました。それはの頭部のalter/2
を体のalter/2
と置き換えました。クイックPrologの解剖学のレッスン:
alter([H|T], [X|Y]) :- change(H, X), alter(T, Y).
------------------- --------------------------
"the head" "the body"
だから、Prologはalter([keith,is,very,cool], B)
を証明するために」、言った私は= [H|T]
[keith,is,very,cool]
と= [X|Y]
B
とalter([H|T], [X|Y])
を証明しなければならない(プロローグは賢明な方法でこれらの変数名を管理します。)だから今Prologは置き換えられます。 。。change(H, X), alter(T, Y)
とアクティブクエリ、[H|T]
= [keith|[is,very,cool]]
と= [X|Y]
B
を除くほか、トレースに印刷されますので、何がある:今すぐ
Call: (8) change(keith, _G2756) ? creep
Prologはchange/2
という最初の節を見てください。それはchange(keith, he)
です。だからプロローグは "ああ!X = he
:OK、私はちょうど私があるalter/2
のボディ、の次のステップを見て、二前に始まっそのクエリを完了する必要がある「とし、プリントが
Exit: (8) change(keith, he) ? creep
Prologは今、言う」:
Call: (9) change(is, _G2759) ? creep
:
Call: (8) alter([is, very, cool], _G2757) ? creep
まあ、直前のように、Prologは今alter/2
の本体とalter/2
クエリを交換し、それが今証明しなければならないことを意味しており、それを履行しようとしています
change/2
の最初の句が一致しないため、これは少し面白いです。 Prologはkeith
をis
と統一できないため、失敗し、2番目の句に移動します。それは第三節に移り、それ自体でis
を統合して、very
でis
を統一することはできません:、このプロセスは繰り返される
Exit: (9) change(is, is) ? creep
を非常に/あまりにも、クール/クール手渡し、その後、Prologは、リストの成分が不足し、あなたが注意を払っている場合は
Call: (11) alter([], _G2766) ? creep
Exit: (11) alter([], []) ? creep
は、あなたが匿名の変数とquery行には、プロローグは、質問を変えていることを意味するCall:
を開始していることに気づくべきであり、Prologは質問に答える際に:あなたはalter/2
のあなたの基本ケースを入力します。 、行はで始まります。 Prologの実行モデルについて他のことを教えてくれる行がいくつかあります:Retry:
とFail:
です。しかし、クエリは実際に最初の試行で動作するため、ここにはそれらがありません。
ここからは、すべてが正常に統合され、Prologが基本的に完了したので、Exit
が得られます。しかし、これはここで起こっている「構築」:
Exit: (11) alter([], []) ? creep
Exit: (10) alter([cool], [cool]) ? creep
Exit: (9) alter([very, cool], [too, cool]) ? creep
Exit: (8) alter([is, very, cool], [is, too, cool]) ? creep
Exit: (7) alter([keith, is, very, cool], [he, is, too, cool]) ? creep
何ここで起こっていることはalter([], [])
が証明されていることであるので、外側のコール(そこに番号を気づく;彼らはコールスタックについてあなたの言っている)に戻りますつまり、Prologはalter([cool], [cool])
が真であることを証明しました。つまり、alter([very, cool], [too, cool])
が真であることが証明されたことを意味します。これは単なるテール再帰であり、期待通りのものです。最後に、クエリが成功したと出力します。
B = [he, is, too, cool] .
ここには、実際にはメモリアドレスが表示されません。
これらの変数が戻る前に、値が割り当てられているか、新しいYはZの尾の値を取るだろうが、Zは、メモリ上のスポットへの参照のみであるためと思われますか?
「通常の」プログラミング言語では、いくつかの値を持つ関数を呼び出し、1つの値を戻り値として返します。プロローグは通常のプログラミング言語ではありません。あなたは関数を定義していない、あなたは関係を定義している。リレーションは関数よりも制約が少なくなります。パラメータが入力であり、出力が出力であることがあります。 Prologの変数は「メモリ内のスポットへの参照」ではありません。それらは単にデータの名前です。彼らは計算されているかどうかによって、地面または無料にすることができます。
Prologでの評価の各ステップは、Prologが自由変数のバインディングを検索しています。これは統一と呼ばれ、Prologの基本的な実行モデルです。 change(keith, X)
のようなクエリを発行するときは、プロローグにchange(keith, X)
が真であることを証明し、それを真にする値Xを指定するように要求しています。 Prologはそれを見て、true, X = he
と戻ってくるでしょう。しかし、change(X, he)
と尋ねることもでき、Prologはそれを見て、true, X = keith
と言うでしょう。これは、関数ではなくリレーションにする要素の一部です。 change(X, Y)
と言うこともでき、true, X = keith & Y = he; X = very & Y = too; X = Y
で返ってくるでしょう。その結果の多重度は、あなたがリレーションを扱い、関数ではないことを知っている別の方法です。
変数は「メモリ内のスポット」ではなく、名前と値の間のバインディングであり、Prologはその途中で評価のどのステップでもそのバインディングを確立できますまたは計算中に、しかし成功した計算の途中でも!
あなたの本を振り返ってみると、これについて詳しく説明しています。そこでは最高のプロローグの本の1つで、それは確かにこのことを詳述しています。しかし、私はこれがとにかく助けて欲しい!
メモリ内のメモリアドレス参照やスポットについて話すことはありません(このような用語を使っていますか?)。 Prologの操作モデルには、変数、統一、パターンマッチングがあります。そのような観点から考えようとすると、より簡単になるかもしれません。 –
'alter([非常に]、[非常に])'は成功し、意図しましたか? – false