我正在使用管道来传达两个Prolog进程,每次我到达read/2
谓词来读取我的管道中的消息时,该程序被阻止并保持这样。我无法理解为什么会这样(我尝试过非常简单的程序),最后我意识到了三件事:
write/2
发送邮件时,发件人流程都必须以.\n
结束该邮件。如果消息没有像这样结束,接收者进程将卡在read/2
谓词。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
没有阻止(假设消息没有被刷新)?
谢谢!
答案 0 :(得分:2)
有效的Prolog读取术语始终以句点end char (* 6.4.8 *)
结尾。在6.4.8其他令牌中,标准为:
结束字符后面应跟一个布局字符或
%
。
所以这就是标准要求的。
除了空格,制表符和其他布局字符以及%
之外,句点之后的换行符是结束读取术语的一种可能性。但是,由于ttys和相关缓冲的普遍存在,只需坚持换行就好了。
需要结束字符的原因是Prolog语法允许中缀和后缀运算符。考虑作为输入
f(1) + g(2).
在阅读f(1)
时,您可能认为这已经是整个学期,但您仍需要等待这段时间,以确保此后没有中缀或后缀。
另请注意,您必须使用writeq/1
或write_canonical/1
来生成可以回读的输出。您无法使用write/1
。
作为示例,请考虑write([(.)+ .]).
首先,这是有效的语法。点后面紧跟着其他一些角色。备注.
通常在结尾处称为句点,而在Prolog文本中称为点。
write/1
会将其写为[. + .]
。请注意,第一个.
后面跟一个空格。所以当回读这个文本时,
只会读取[.
。
还有许多其他丑陋的例子,例如这个,通常它们不会打击你。但是一旦你被击中,你就会被击中......