5

OS X 7 で SWI-Prolog バージョン 6.4.1 を使用していますが、述語で次の予期しない動作が発生していますcurrent_functor/2

事実を考えると

p(a).
q.

クエリに対するこれらの回答を取得します。

?- current_functor(p, Y).
Y = 1 

?- current_functor(q, Y).
false.

?- current_functor(q, 0).
true.

2 番目と 3 番目のクエリが明らかに矛盾しているように見えるだけでなく、2 番目のクエリの失敗は、次のように説明されている SWI-Prolog リファレンス マニュアルと一致していないようですcurrent_functor/2

current_functor(?Name, ?Arity) Name を名前に、Arity をシステムに知られているファンクターのアリティに順次統合します。

述語がこのように機能している理由を理解できる人はいますか?

編集:

特定の0アリティのものを含め、述語が定義されているかどうかをテストするという私の特定の問題を解決するという点で、私は偽のアドバイスに従い、次のように書くことになりました:

current_pred(P) :-
    current_predicate(P/_).
4

2 に答える 2

4

pl-funct.c の 391 行目にバグがあると思います。その行は読んだ

if ( fd && fd->arity > 0 && (!nm || nm == fd->name) )

今、私は修正しfd->arity >= 0てテストしようとします...

編集どうやらうまくいった:

1 ?- [user].
yy.
|: 
% user://1 compiled 0.00 sec, 2 clauses
true.

2 ?- current_functor(yy,X).
X = 0 ;
false.

コミットしてみますが、完全なソースへの git アクセス権がないと思います...

edit確かに、git は私の変更を受け入れることを拒否します... SWI-Prolog メーリング リストで報告します。

于 2013-10-28T19:44:17.270 に答える
4

TL;DR: しないでください!

current_functor/2は SWI 固有の組み込み述語であり、他のどこにもありません (歴史的に関連のある唯一の DECsystem 10 を除く)。この述語の理由は、SWI におけるファンクタの特定の表現に関連しています。簡単に言うと、SWI は各ファンクターを使用する前に登録する必要があります。(その前に、関連するアトムを登録する必要があります。) ファンクターが使用されなくなったらどうなりますか? それはまだ存在しますか?このリソースはガベージ コレクションされますか?

あなたの質問に答えるには: current_functor/2ファンクターに対してのみ成功します。アリティ 0 のファンクタはありません。アリティ 0 の項はアトムと呼ばれ、別の方法で処理されます。

いずれにせよ、1 人の人物によって維持される 1 つの実装に依存するコードを記述します。大規模なプロジェクトにはあまり安全な賭けではありません。

他の Prolog システムの動作は異なります。max_arityアトムも登録する必要がありますが、それ以上のグローバル リソースを使用せずに任意のファンクターを構築できます。このため、多くのシステムが提供していますcurrent_atom/1

しかし、まさにその述語でさえ定義が不十分です。結局のところ、原子がまだ存在するということは何を意味するのでしょうか? 最適化コンパイラはアトムを削除して、その意味を変更できますか? アプリケーションが使用する機密アトムを、他の点では無害に見えるクエリ コードで検査する手段ですか?

これはすべて、本当にワームの缶です。どうしても避けてください。代わりに使うかもしれませんcurrent_predicate


とはいえ、それでも必要だと思う場合は、次のことを行ってください。

current_f(F, A) :-
   current_functor(F, A).
current_f(F, 0) :-
   current_atom(F).
于 2013-10-28T21:18:12.490 に答える