5

SWI-Prolog (マルチスレッド、64 ビット、バージョン 7.3.5) を使用して、段階的に進めます。

  1. モジュールでを定義します(発音: " di-SEE-goh "):a//1dcgAux

    :- モジュール(dcgAux,[a//1])。
    
    a(0) --> [].
    a(s(N)) --> [a]、a(N)。
    
  2. とを使用して、次のクエリを実行しphrase/2ますapply:foldl/4

    ?- use_module([ライブラリ(適用),dcgAux])。
    真実。
    
    ?- フレーズ( foldl( a,[s(0),s(s(0))]),[a,a,a]).
    。
    
    ?- フレーズ( foldl(dcgAux:a,[s(0),s(s(0))]),[a,a,a])。
    。
    
    ?- フレーズ(適用:foldl(dcgAux:a,[s(0),s(s(0))]),[a,a,a]).
    。
    
    ?- 句(適用:foldl( a,[s(0),s(s(0))]),[a,a,a])。
    エラー: apply:foldl_/4: 未定義のプロシージャ: apply:a/3
    

    ねえ!かなりの驚きであり、良いものではありません。未知の未知のものを見逃していませんか?

  3. 上記の苛立たしい行動を取り除くには、まずその原因を突き止める必要があります。

    ?- import_module(適用、M)、M=ユーザー。
    。
    
    ?- 句(適用:foldl(a,[s(0),s(s(0))]),[a,a,a])。
    エラー: apply:foldl_/4: 未定義のプロシージャ: apply:a/3
    
    ?- add_import_module(適用、ユーザー、終了)。
    真実。
    
    ?- import_module(適用、M)、M=ユーザー。% シック!
    M = ユーザー。% `?- import_module(apply,user).` 失敗!
    
    ?- 句(適用:foldl(a,[s(0),s(s(0))]),[a,a,a])。
    

どうしたの?私がそれを見る方法はこれです:

  • に渡されるゴールのモジュール拡張foldl/4は制限されています。
  • のSWI-Prolog マニュアルページimport_module/2からの引用:

    すべての通常のモジュールは、システムからインポートするユーザーからのみインポートします。

  • SWIlibrary(apply)は からのみ「継承」しますsystemが、 は継承しませんuser

  • applyモジュールを複製applY(および新しいモジュール名を伝搬) すると、次のことがわかります。

    ?- use_module(applY)。
    真実。
    
    ?- フレーズ( applY :foldl(a,[s(0),s(s(0))]),[a,a,a]). % だった: エラー
    true。% 今OK!
    

私がどのように進めるべきか、どのように進めるべきかについて、あなたのアイデアを共有してください!

(他の Prolog プロセッサで同様の実験をまだ行っていません。)

4

1 に答える 1

6

これは、Quintus の伝統における述語ベースのモジュール システムに固有の機能/バグです。つまり、このモジュール システムは最初に Quintus Prolog 用に開発されました。その後、SICStus (0.7 1以降)、(多かれ少なかれ) 13211-2、YAP、(いくつかの変更を加えて) SWI によって採用されました。

ここでの問題は、明示的な修飾が​​正確に何を意味するかです。目標がメタ述語でない限り、物事は自明に解決可能です。最も内側の修飾のモジュールを取ります。ただし、メタ述語を作成したら、メタ引数にそのモジュールを通知する必要があります。か否か。メタ引数が通知される場合、コロンが呼び出しコンテキストを設定すると言います。そうでない場合は、その目的のために他の手段が必要です。

Quintus の伝統では、メタ引数が考慮されます。あなたが見る結果で。結果として、同じモジュール内の同じメタ述語の 2 つの実装を直接比較することはできません。コロンを介して呼び出しコンテキストを変更しない、最も顕著なIFECLiPSeなどの他のアプローチがあります。これには長所と短所があります。ケースバイケースで比較するのが一番です。

ここ最近の事例です。ラムダと、それらがSICStus 、 SWI、およびECLiPSeのモジュールにどのように配置されているかを見てみましょう。

Quintus/SICStus/YAP/SWI モジュール システムに関しては、可能な限り保守的な方法で使用したいと考えています。あれは:

  • 明示的な修飾はありません。中置記号:は内部的なものと考えてください

  • クリーンでチェック可能なメタ宣言 - 相互参照が問題を検出できるかどうかを確認するためだけに未定義の述語を意図的に挿入します (SWI ではcheckormakeです)。

  • 共通のサブセットを使用し、多くの付箋を避けます - 多くの善意の拡張機能があります...

  • 適切なモジュールを追加して再エクスポートし、ダミーの定義を追加します。同様に、名前を変更する代わりに、インターフェイス モジュールからインポートします。

  • モジュールシステムには本質的にいくつかの制限があることに常に注意してください。どんなにひねっても、回しても。完全にシームレスなモジュール システムはありません。モジュールのまさにその目的は、コードと懸念事項を分離することです。


1: 正確に言うと、Quintus モジュールの SICStus の適応は:、モジュールに依存する引数のみをmeta_predicate宣言に含めました。0..9に基づく高階プログラミングにとって非常に重要な整数は、 2011-03-08 でリリースされた 4.2.0call/Nで約 20 年後に導入されました 。

于 2015-08-21T16:03:27.633 に答える