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

时间:2013-04-03 17:03:25

标签: 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
  4. 示例:

    这不起作用:

    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 个答案:

答案 0 :(得分:2)

有效的Prolog读取术语始终以句点end char (* 6.4.8 *)结尾。在6.4.8其他令牌中,标准为:

  

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

所以这就是标准要求的。

除了空格,制表符和其他布局字符以及%之外,句点之后的换行符是结束读取术语的一种可能性。但是,由于ttys和相关缓冲的普遍存在,只需坚持换行就好了。

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

f(1) + g(2).

在阅读f(1)时,您可能认为这已经是整个学期,但您仍需要等待这段时间,以确保此后没有中缀或后缀。

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

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

write/1会将其写为[. + .]。请注意,第一个.后面跟一个空格。所以当回读这个文本时, 只会读取[.

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