Как настроить прологскрипт

Я устанавливаю следующие правила, чтобы определить, есть ли связь между двумя элементами:

directReference(A,B) :- projectReferences(A,B).
transitiveReference(A,C) :- directReference(A,B),directReference(B,C).
transitiveReferenceD1(A,D) :- transitiveReference(A,C),directReference(C,D).
transitiveReferenceD2(A,E) :- transitiveReferenceD1(A,D),directReference(D,E).

Могу ли я написать PrologScript, который будет проверять все эти запросы на факт? Хотя я планирую использовать Ruby&Rake, кто-то пытается сделать неинтерактивный вызов из PHP здесь, и это не сработало. Я также видел этот ответ и попробовал ответ Каарела. Я только что добавил новый opts_spec:

opts_spec(
    [ [opt(day), type(atom),
        shortflags([d]), longflags(['term', 'day']),
        help('name of day')]

    , [opt(goal),
        shortflags([g]), longflags([goal]),
        help('goal to be called')]

    , [opt(projectReferences), type(atom),
        shortflags([pr]), longflags(['term', 'projectReferences']),
        help('Project Reference lookup')]
    ]
).

Затем я скомпилировал с:

.\swipl.exe -o day.exe -g main -c "D:\DevProjects\AskJoe\Output\Sample.pro"

И запустил его с помощью:

./day.exe -g "day(Sunday)"

И получил ошибку:

ОШИБКА: Ошибка инициализации Prolog: ОШИБКА: validate_opts_spec/1: Ошибка домена: unique_atom' expected, foundterm' (неоднозначный флаг)

Моя цель состоит в том, чтобы эта работа:

./day.exe -g "transitiveReference('a','b')"

Мне не нравится компилировать "day.exe" для запуска скрипта (в соответствии с docs в этом часто нет необходимости), но я не нашел другого способа передать аргументы в правила.

Я видел базовое введение на swi-pl.org, которое мало помогло. Он не объясняет, как перейти от примера файла script.sh к выполнению ./eval 1+2. На самом деле, пример - это комментарий, поэтому я совершенно потерялся.


person P.Brian.Mackey    schedule 21.02.2015    source источник
comment
Я считаю, что .\swipl.exe нужен только для систем Windows.   -  person Shon    schedule 21.02.2015


Ответы (2)


Вот очень грубый пример программы на PrologScript, которая считывает свои аргументы как единую цель (которая может быть составной), вызывает ее и затем завершает работу. Он должен работать в системах *nix и был протестирован на OS X. Это всего лишь небольшая вариация пример программы, приведенный для использования PrologScript в документах SWI:

#!/usr/bin/env swipl

:- initialization main.

query :-
        current_prolog_flag(argv, Argv),
        concat_atom(Argv, ' ', Atom),
        read_term_from_atom(Atom, Term, []),
        call(Term).

main :-
        catch(query, E, (print_message(error, E), fail)),
        halt.
main :-
        halt(1).


projectReferences(valueA, valueB) :- writeln('I was called!').
directReference(A,B) :- projectReferences(A,B).
transitiveReference(A,C) :- directReference(A,B),directReference(B,C).
transitiveReferenceD1(A,D) :- transitiveReference(A,C),directReference(C,D).
transitiveReferenceD2(A,E) :- transitiveReferenceD1(A,D),directReference(D,E).

После сохранения этого файла, например, как cli_test.pl, вам необходимо изменить права доступа к файлу, чтобы операционная система распознала его как исполняемый файл:

chmod -x scratchboard.pl

После этого вы сможете вызывать файл как обычный исполняемый файл из командной строки:

$ path/to/the/file/scratchboard.pl 'transitiveReferenceD1(A,D).'
I was called!

Примечание:

  • Оцениваемая цель просто передается как один аргумент. Затем query/0 извлечет этот аргумент с помощью current_prolog_flag/2, прочитает его как терм Пролога и вызовет его.
  • Так как программа не работает в интерактивном режиме, единственный результат будет результатом явных императивов записи, например, когда catch/3 (в теле main/0) вызывается ошибкой или если projectReferences/2 вызывается успешно.

Использование library(optparse) кажется целесообразным для более сложного интерфейса cli, но не обязательно для заявленной вами цели простого запроса целей в файле.

Я понимаю, что использование подхода PrologScript для работы в Windows несколько отличается. Немного информации можно найти здесь: http://www.swi-prolog.org/FAQ/PrologScript.html

person Shon    schedule 21.02.2015
comment
Я использую ОСХ. Я скопировал код и сохранил его как script3.pl. Затем я запускаю его в bash с помощью sudo ./script3.pl 'transitiveReferenceD1(A,D).' и получаю command not found. Я запустил which swipl и получил /usr/local/bin/swipl, поэтому я попробовал #!/usr/local/bin swipl и получил command not found. - person P.Brian.Mackey; 21.02.2015
comment
@P.Brian.Mackey хм... единственное, о чем я сразу же могу подумать: вы предоставили права на исполняемый файл файлу, используя $ chmod +x script3.pl ? - person Shon; 21.02.2015
comment
Ой! Так это работает! Здорово! Я добавлю эту часть инструкции к своему ответу и предложу это изменение в документах SWI. Я уже сталкивался с этим камнем преткновения в прошлом. Тем, кто пишет документацию и дает советы, слишком легко забыть, сколько очевидных деталей становятся очевидными только после многократного использования. - person Shon; 21.02.2015

Итак, у меня все это заработало, а затем, после нескольких прогонов, все просто остановилось. Я начал получать ошибки «Отказано в доступе к плохому интерпретатору». Все, что я могу сказать, это то, что это как-то связано с hashBang. Обходной путь для меня состоял в том, чтобы создать сценарий оболочки вокруг вызова swipl:

shellscript.sh

#!/bin/bash
swipl -s script4.pl 'projectReferences(A,D).'

Затем я продолжил использовать пример aBathologist, но только снял hashBang:

:- initialization main.

query :-
        current_prolog_flag(argv, Argv),
        concat_atom(Argv, ' ', Atom),
        read_term_from_atom(Atom, Term, []),
        call(Term).

main :-
        catch(query, E, (print_message(error, E), fail)),
        halt.
main :-
        halt(1).


projectReferences(valueA, valueB) :- writeln('I was called!').
directReference(A,B) :- projectReferences(A,B).
transitiveReference(A,C) :- directReference(A,B),directReference(B,C).
transitiveReferenceD1(A,D) :- transitiveReference(A,C),directReference(C,D).
transitiveReferenceD2(A,E) :- transitiveReferenceD1(A,D),directReference(D,E).
person P.Brian.Mackey    schedule 21.02.2015