Модуль расширения целей, передаваемых в библиотечные мета-предикаты

Используя SWI-Prolog (многопоточный, 64 бита, версия 7.3.5), мы продвигаемся шаг за шагом:

  1. Определить DCG нетерминал a//1 в модуле dcgAux (произносится: " ди-с-го "):

    : - модуль (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]).
    ОШИБКА: применимо:foldl_/4: неопределенная процедура: применимо: a / 3
    

    нет! Совершенно неожиданно, но не очень. Мы пропустили некоторые неизвестные неизвестные?

  3. Чтобы избавиться от вышеупомянутого раздражающего поведения, мы должны сначала выяснить причину (ы), вызывающую его:

    ?- import_module (применить,M), M= пользователь.
    ложь?- фраза (применимо:foldl(       a,[s(0),s(s(0))]),[a,a,a]).
    ОШИБКА: применимо:foldl_/4: неопределенная процедура: применимо:a/3?- add_import_module(применить, пользователь, конец).
    правда.?- import_module(применить,M), M= пользователь.   % sic!
    М = пользователь.                            % `?- import_module(применить, пользователь).` не удалось!?- фраза (применимо:foldl(       a,[s(0),s(s(0))]),[a,a,a]).
    правда
    

В чем дело? Я вижу это так:

  • Модуль расширения цели передан foldl/4 ограничено.
  • Цитирование со страницы руководства SWI-Prolog на import_module/2:

    Все обычные модули импортируют только от пользователя, который импортирует из системы.

  • SWI-х library(apply) только "наследует" от system, но нет user,

  • Если мы клонируем модуль apply в applY (и распространяем имя нового модуля), мы наблюдаем:

    ?- use_module (applY).
    правда.?- фраза (applY:foldl(       a,[s(0),s(s(0))]),[a,a,a]). % было: ОШИБКА
    правда % сейчас нормально!
    

Пожалуйста, поделитесь своими идеями о том, как я мог / должен действовать!

(Я еще не проводил подобный эксперимент с другими процессорами Prolog.)

1 ответ

Решение

Это неотъемлемая особенность / ошибка модульных систем на основе предикатов в традиции Quintus. То есть эта модульная система была впервые разработана для Quintus Prolog. Впоследствии он был принят SICStus (после 0,7 1), затем (более или менее) 13211-2, затем YAP и (с некоторыми изменениями) SWI.

Проблема здесь в том, что именно означает явная квалификация. Пока цель не мета-предикат, вещи тривиально разрешимы: возьмите модуль самой внутренней квалификации. Однако, как только у вас есть мета-предикаты, мета-аргументы должны быть проинформированы об этом модуле; или нет. Если мета-аргументы проинформированы, мы говорим, что двоеточие устанавливает контекст вызова, если нет, то для этой цели нужны другие средства.

В традиции Квинта мета-аргументы принимаются во внимание. С результатом вы видите. Как следствие, вы не можете напрямую сравнивать две реализации одного и того же мета-предиката в одном и том же модуле. Существуют и другие подходы, особенно IF и ECLiPSe, которые не изменяют контекст вызова через двоеточие. Это имеет свои преимущества и недостатки. Лучше всего сравнить их в каждом конкретном случае.

Вот недавний случай. Возьмите лямбды и то, как они помещаются в модуль в SICStus, в SWI и в ECLiPSe.

Что касается модульной системы Quintus/SICStus/YAP/SWI, я бы предпочел использовать ее максимально консервативно. То есть:

  • нет явной квалификации, рассмотрим инфикс : как нечто внутреннее

  • чистые, проверяемые мета-объявления - специально вставьте неопределенный предикат, чтобы посмотреть, способна ли перекрестная ссылка обнаружить проблему (в SWI это check или же make).

  • используйте общее подмножество, избегайте множества наворотов - есть много хороших расширений...

  • делать более универсальные вещи пешеходным способом: реэкспорт, добавив соответствующий модуль и добавить фиктивное определение. Точно так же, вместо переименования, импортируйте вещи из интерфейсного модуля.

  • всегда помните, что модульные системы имеют некоторые ограничения. Неважно, как вы крутите или поворачиваете его. Не существует полностью цельной модульной системы, поскольку самой целью модулей является разделение кода и задач.


1: Чтобы быть точным, адаптация модулей Quintus SICStus включала только : для чувствительных к модулю аргументов в meta_predicate деклараций. Целые числа 0..9, которые так важны для программирования более высокого порядка на основе call/N были введены только около 20 лет спустя в версии 4.2.0 2011-03-08.

Другие вопросы по тегам