Всегда ли необходимо использовать '.\ N' при чтении потоков в Прологе?

Я использую каналы для связи двух процессов Prolog, и каждый раз, когда я достиг read/2 Предикат прочитал сообщение из моей трубы, программа заблокировалась и так и осталась. Я не мог понять, почему это произошло (я попробовал с очень простыми программами), и в конце я понял три вещи:

  1. Каждый раз, когда я использую write/2 чтобы отправить сообщение, процесс отправителя должен завершить это сообщение .\n, Если сообщение не заканчивается таким образом, процесс получателя застрянет на read/2 сказуемое.
  2. Если отправитель не сбрасывает выходные данные, сообщение поэтому не остается в буфере канала. Это может показаться очевидным, но это было не для меня в начале.
  3. Хотя, когда сообщение не сбрасывается, read/2 блокирует, wait_for_input/3 не блокирует вообще, поэтому нет необходимости flush_output/1 в таком случае.

Примеры:

Это не работает:

example1 :-
    pipe(R,W),
    write(W,hello),
    read(R,S). % The program is blocked here.

Это тоже не сработает:

example2 :-
    pipe(R,W),
    write(W,'hello.\n'), 
    read(R,S). % The program is blocked here.

Пока эти двое работают

example3 :-
    pipe(R,W),
    write(W,'hello.\n'),
    flush_output(W),
    read(R,S).
example4 :-
    pipe(R,W),
    write(W,'hello.\n'),
    wait_for_input([W],L,infinite).

Теперь мой вопрос почему? Есть ли причина, по которой Prolog только "принимает" полные строки, заканчивающиеся точкой при чтении из канала (фактически, при чтении из любого потока, который вы можете захотеть прочитать)? И почему read блок в то время как wait_for_input/3 нет (при условии, что сообщение не сброшено)?

Спасибо!

1 ответ

Решение

Действительный термин Пролог всегда заканчивается точкой, называемой end char (* 6.4.8 *), А в 6.4.8 других токенов стандарт гласит:

Конечный символ должен сопровождаться символом макета или %,

Так что это то, что требует стандарт.

Новая строка после периода - это одна из возможностей завершить термин для чтения, кроме пробела, табуляции и других символов макета, а также %, Тем не менее, из-за распространенности ttys и связанной с этим буферизации, кажется хорошим соглашением просто придерживаться новой строки.

Причина, по которой нужен конечный символ, заключается в том, что синтаксис Prolog разрешает операторы инфикса и постфикса. Рассматривать как ввод

f(1) + g(2).

при чтении f(1) Вы можете полагать, что это уже весь термин, но вам все еще нужно дождаться периода, чтобы убедиться, что после него нет инфикса или постфикса.

Также обратите внимание, что вы должны использовать writeq/1 или же write_canonical/1 производить вывод, который можно прочитать обратно. Вы не можете использовать write/1,

В качестве примера рассмотрим write([(.)+ .]). Во-первых, это правильный синтаксис. За точками сразу же следует какой-то другой символ. Отметьте . обычно называется точкой в ​​конце, тогда как в тексте Пролога это называется точкой.

write/1 напишу это как [. + .], Обратите внимание, что первый . теперь следует пробел. Поэтому, когда этот текст читается обратно, только [. будет прочитано

Есть много других уродливых примеров, таких как этот, обычно они не бьют вас. Но как только тебя бьют, тебя бьют...

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