2015-02-21 5 views
3

У меня есть сценарий оболочки, script.sh:Как вывести результат в оболочку?

#!/bin/bash 
FIRST_ARGUMENT="$1" 

swipl -s script4.pl $FIRST_ARGUMENT 

prolog.pl:

:- 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). 

b(a). 
a(c, d) :- writeln('I was called!'). 

Теперь, если я позвоню скрипт из командной строки:

sh s.sh 'a(c,d).' 

Выведет "I was called!".

Но если я выполнить запрос, кроме да/нет ответа:

sh s.sh 'b(a).' 

Все это говорит мне: script4.pl compiled 0.00 sec, 7 clauses. Когда то, что я хочу, является «истинным», потому что был найден факт, соответствующий совпадению. Как я могу получить результат?

Я хочу запросить мою программу Prolog от Rake (производная от Ruby). Я считаю, что сценарий - это простой способ сделать это, но, может быть, он недостаточно мощный?

+1

Вам нужно решить, действительно ли вам нужно позвонить в свою программу как сценарий, а не использовать верхний уровень (интерпретатор).Практически нет смысла использовать скрипт вместо верхнего уровня, за исключением, может быть, обработки пакетного текста (?). –

+0

@Boris Я обновил вопрос. Возможно, есть что-то, что я могу сделать, чтобы сделать это лучше. –

+1

Вы можете отключить информативное сообщение о времени, затраченном на компиляцию файла, и количество предложений в нем с помощью опции командной строки SWI-Prolog '--quiet' или' -q'. –

ответ

1

Один простой, правда, грубо, способ добавить writeln(true) и writeln(false) каждому из успеха и не положения о main/0 соответственно:

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

Хотя я уверен, что есть лучшее решение, которое будет иметься. ..

+1

Хотя метод I'L'I очень забавный, я использовал этот метод, потому что он работает на windows и mac. Мне нужны оба. –

+0

Этот метод кажется более общим, в ограниченном смысле, что он оставляет его в коде Пролога, чтобы решить, какой тип вывода должен генерировать. И наоборот, метод I'L'I, похоже, дает определенную гарантию на стороне unix, гарантируя определенные результаты из сценария оболочки. Я думаю, что точка импорта - это вывод «true». и «ложь». только имеют определенный смысл для Prolog на верхнем уровне. Когда мы используем программы Prolog в качестве исполняемых файлов, связанных с другими программами, мы просто хотим, чтобы они выводили любые данные, которые нам нужны. Использование Пролога для проверки фактов - очень частный случай этого. –

+1

@aBathologist, Хорошо сказано. Метод в моем ответе был чем-то, что я придумал по прихоти. В то время как это * забавно *, как выразился P.Brian.Mackey, я думаю, что использование решения, которое имеет пролог, касается самого себя, должно быть предпочтительным. Приятно видеть такое мышление со всеми ответами, так как оно позволяет выйти за пределы того, что могло быть сделано раньше. –

1

Обычно сценарии оболочки возвращают ноль при успешном завершении и целое число, отличное от нуля, интерпретируемое как код ошибки, при сбое. Таким образом, вы можете использовать стандартный предикат halt/1 для возврата либо нулевого, либо, например, один в зависимости от вашего запроса, соответственно, с успехом или неудачей. Вы уже делаете это, но вы можете сделать его немного более ясно, что-то вроде:

main :- 
    ( query -> 
     halt(0) 
    ; halt(1) 
    ). 

Если запрос может выбросить исключение, обернуть его, используя стандартный catch/3 предикат:

main :- 
    ( catch(query, _, fail) -> 
     halt(0) 
    ; halt(1) 
    ). 

Вы можете также использовать исключение для выбора значения выхода:

main :- 
    ( catch(query, Error, error_handler(Error)) -> 
     halt(0) 
    ; halt(1) 
    ). 

error_handler(error1) :- halt(2). 
error_handler(error2) :- halt(3). 
... 

в этом случае, ноль будет означать успех, один будет означать провал, и любое другое целое число будет означать соответствующег ошибка ng.

2

Поскольку вывод того, что вы хотите, чтобы сделать пролог, обычно выполняется строго внутри его интерактивной оболочки, это одна из тех вещей, для которой требуется некоторый тип реализации crude. Этот конкретный можно было бы рассмотреть на крайнем конце, , но он действительно работает.

#!/bin/bash 
FIRST_ARGUMENT="$1" 

swipl -l script4.pl $FIRST_ARGUMENT',halt(n).' 2>&1 | sed 's/ERROR: halt\/1.*/True/g' 

Результат:

$ sh s.sh 'b(a)' 
True 

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

+1

Любой, кто пытается это сделать, внимательно следите за этим ответом. Обратите внимание, что аргумент 'b (a)' НЕ имеет '.' потому что это часть команды оболочки сейчас. –