В SWI-Prolog при вызове copy_stream_data, как я могу избежать подсказки '|:'?

Я реализовал программу cat в SWI-Prolog, используя copy_stream_data.

Файл args.pl:

:- module(args, [withFilesOrUserInput/2]).

withFilesOrUserInput(StreamFunction, []) :-
    call(StreamFunction, user_input).

withFilesOrUserInput(StreamFunction, [Filename]) :-
    withFile(StreamFunction, Filename).

withFilesOrUserInput(StreamFunction, [Head|Tail]) :-
    withFile(StreamFunction, Head),
    withFilesOrUserInput(StreamFunction, Tail).

withFile(StreamFunction, Filename) :-
    open(Filename, read, StreamIn),
    call(StreamFunction, StreamIn),
    close(StreamIn).

Файл cat.pl:

:- use_module(args).

main(Argv) :-
    withFilesOrUserInput(catStream, Argv).

catStream(Stream) :-
    copy_stream_data(Stream, user_output),
    flush_output(user_output).

Когда я использую программу для cat от stdin до stdout, она печатает подсказку |:, где ожидает ввода от stdin. Как я могу избежать этой подсказки?


person Christian Hujer    schedule 26.08.2015    source источник
comment
(Не ответ, а комментарий к вашему коду) Существует setup_call_cleanup/3 для правильной обработки таких ситуаций. В вашей версии неудачный или ошибочный call(StreamFunction, StreamIn) не закроет поток. А если у вас будет несколько ответов, вы попытаетесь получить доступ к уже закрытому потоку.   -  person false    schedule 27.08.2015
comment
Да, я все еще учусь правильно выполнять ввод-вывод в Prolog. Посмотрим, когда я научусь правильно использовать setup_call_cleanup/3, может быть, сегодня, может быть, завтра. Однако я не понимаю, как несколько ответов приведут к доступу к уже закрытому потоку, но, может быть, в этом есть что-то, чего я еще не понимаю?   -  person Christian Hujer    schedule 27.08.2015


Ответы (1)


Подсказка |: появляется только тогда, когда stdout является терминалом. Он не появляется, когда stdout является файлом. Таким образом, это не вызовет мусора на выходе, когда ваш вывод перенаправляется в файл. Но все равно это не приятно.

Чтобы избежать подсказки, очистите ее с помощью встроенного предиката prompt< /a>, например: prompt(_, ''), который вы можете вставить в свой предикат main(Argv):

main(Argv) :-
    prompt(_, ''),
    withFilesOrUserInput(catStream, Argv).

Вы также можете поместить предложение с предикатом prompt(_, '') в начале программы, вставив следующее в начало кода:

 :- prompt(_, '').

Вы даже можете сделать это в модуле после предложения :- module().

person Christian Hujer    schedule 26.08.2015
comment
Избегайте этого взлома любой ценой. - person false; 27.08.2015
comment
@false Почему вы думаете, что этого взлома следует избегать? Я не знаю, чтобы какой-либо другой язык начал подсказки таким странным образом только потому, что программа начинает чтение с stdin, когда stdout является терминалом. Это даже не логично, я думаю, это баг. Запрашивать имеет смысл только тогда, когда оба, stdin и stdout, являются терминалом. Но когда программа вызывается как prolog -qt main cat.pl <file.txt, нет смысла показывать подсказку. - person Christian Hujer; 27.08.2015
comment
Это хак, потому что вы меняете глобальное состояние для чего-то, что было написано для интерактивного использования. Хотя в этом есть смысл. Другие, более подходящие системы (например, SICStus) показывают это приглашение только тогда, когда ввод является терминалом. - person false; 27.08.2015