stream - 在Prolog中读取流时是否总是需要使用 '.\n'?

标签 stream prolog pipe iso-prolog

我正在使用管道来通信两个 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 不会(假设消息未刷新)?

谢谢!

最佳答案

有效的 Prolog 读取术语始终以句点结束,称为 end char (* 6.4.8 *)。在 6.4.8 其他标记中,标准如下:

An end char shall be followed by a layout character or a %.

这就是标准的要求。

除了空格、制表符和其他布局字符以及 % 之外,句号后面的换行符也是结束读取术语的一种可能。然而,由于 tty 和相关缓冲的盛行,坚持使用换行符似乎是一个很好的约定。

需要结束字符的原因是 Prolog 语法允许中缀和后缀运算符。考虑作为输入

f(1) + g(2).

当阅读 f(1) 时,您可能会认为这已经是整个术语,但您仍然必须等待句点以确保其后没有中缀或后缀。

另请注意,您必须使用 writeq/1write_canonical/1 来生成可读回的输出。您不能使用write/1

作为示例,请考虑 write([(.)+ .])。 首先,这是有效的语法。这些点后面紧跟着一些其他字符。请注意 . 通常称为末尾的句点,而在 Prolog 文本中则称为点。

write/1 会将其写为 [。 + .]。请注意,第一个 . 现在后面跟着一个空格。所以当这段文字被读回来时 仅读取[.

还有很多其他丑陋的例子,比如这个,通常它们不会打到你。但一旦你被击中,你就会被击中......

关于stream - 在Prolog中读取流时是否总是需要使用 '.\n'?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15793632/

相关文章:

Rust:预期类型 [X],但发现类型 [X]

c - 将管道作为参数传递给 sort -m

php - 使用 Postfix 传输电子邮件

c - fgetc 与 Unix 文件描述符的等价物

java - 桶排序与快速排序

c# - 使用流编写器集成测试功能

prolog - 确定字符类型

prolog - 逻辑引擎中的不确定性(根据本地地理产生合理的相对位置)

list - 遍历图(可能有循环)并返回 Prolog 中的路径

Angular 2 : Set and remove custom pipes?