在Prolog中读取流时是否总是需要使用'.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不阻塞(假设消息没有刷新)?

谢谢!

有效的Prolog读取期总是以句点结尾,称为end char (* 6.4.8 *)。在6.4.8其他标记中,标准读作:

结束字符后跟一个布局字符或%

所以这就是标准的要求。

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

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

f(1) + g(2).

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

还要注意,必须使用writeq/1write_canonical/1来产生可以回读的输出。不能使用write/1

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

write/1将把它写为[. + .]。注意,现在第一个.后面跟着一个空格。所以当这篇文章被重读时,只有[.会被读取。

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

相关内容

  • 没有找到相关文章

最新更新