【问题标题】:Circular buffer in Turbo Prolog 2.0Turbo Prolog 2.0 中的循环缓冲区
【发布时间】:2011-05-27 18:45:57
【问题描述】:

我需要在 TurboProlog 2.0 中编写类似循环缓冲区的东西来计算平均值。我不知道我需要写什么谓词,也不知道如何将它们联系在一起。

【问题讨论】:

  • 我什至不知道他们写了 2.0.而根据谷歌的前 5 名(3 个种子,1 个亚马逊......和这里),没有多少人这样做了。
  • 我可以想到几种方法,但是如果目标是“计算平均值”,为什么需要循环缓冲区还不清楚。你能解释一下为什么一个简单的列表不适合吗?
  • 主要目标是在 turbo prolog 中实现循环缓冲区。计算平均值是他作品的展示。

标签: prolog circular-buffer turbo-prolog


【解决方案1】:

我不确定您的应用程序需要实现哪些“循环缓冲区”功能。一般来说,“缓冲区”是可重用的存储,通常与处理异步通信的 I/O 进程相关联(因此需要一个允许一个进程领先于另一个进程的缓冲区)。 “循环缓冲区”表示一种使用环绕(线性)连续区域的指针(指向有效/未处理数据的开头和结尾)管理可用存储的方法。这比为有效数据的开头维护一个具有固定位置的 FIFO 队列具有优势,因为不需要对未处理的项目进行“洗牌”。

在标准 Prolog 的一般上下文中,不直接支持重写内存位置,这种优势没有意义。即使在 Turbo Prolog 中,也必须准确询问您想要完成什么,以便熟练使用可用的扩展/非标准功能。

这里有一些想法:

  1. Turbo Prolog 支持的列表在某些方面比标准 Prolog 的正确列表更具限制性,并且可能在其他方面更复杂。其中一个限制是,在 Turbo Prolog 中,列表的所有项目都必须属于同一个“域”,这是一个与标准 Prolog 的弱类型字符不同的概念。在 Turbo Prolog 中,域也可以被指定为“参考”域,这是一种允许在子目标之间传递部分绑定的复合项的间接级别。无需过多详细介绍,“循环缓冲区”的一种含义可能是一个“列表”(由参考域形成),它环绕自身(循环参考)。这样的术语可以在许多其他 Prolog 中创建,区别在于它不是一个正确的列表。尽管这样的术语可能是循环的,但它不会成为一个缓冲区(一旦创建),因为列表中的项目无法重写。

  2. Turbo Prolog 支持动态断言和撤回事实,使用元谓词(如 asserta/1assertz/1)允许在开头连续定位新事实或相同谓词的现有事实的结尾(如果需要,也可以在指定的命名“模块”或事实库中使用 Turbo Prolog 术语)。如果您的目标是简单管理 FIFO 队列中的项目,那么这很可能是您想要的方法(至少对于初始实现而言),将项目封装为事实。

  3. Turbo Prolog 还支持具有一些附加功能的“外部”事实库,即外部存储(在内存中或磁盘上)的方式允许持久性和扩展空间超出为内部事实库分配的空间.考虑到通常与循环缓冲区相关的适度的固定大小(因为它们是为了重用而溢出通常通过阻塞输入进程直到输出进程有机会赶上来处理),外部事实库似乎没有提供太多感兴趣,尽管对于长时间运行的进程来说,持久化“缓冲区”的能力可能很有趣。

希望这些建议能够阐明这里真正需要完成的工作。

【讨论】:

    【解决方案2】:

    想来想去,写了如下程序

    % Consumer predicate. If buffer is empty, nothing to take, need to wait for producer predicate.
    
        consumer(BufferBefore, [], _) :- 
            length(BufferBefore, BuffSize), 
            BuffSize = 0, 
            write("Buffer is empty. Waiting for producer"), nl, !, fail.
    
        % If the buffer is not empty, returns first element and removes them from the buffer
        consumer(BufferBefore, BufferAfter, Result) :- 
            car(BufferBefore, Result),
            deletefirst(BufferBefore, BufferAfter).
    
        % Producer predicate. If data and buffer is empty, nothing taken from the data to put in buffer.
        producer([], [], [], [], _) :- write("End of data!."), !, fail.
    
        % Else if buffer is not empty, add first elem from data (and removes them from here) to last position in buffer.
        producer(DataBefore, BufferBefore, DataAfter, BufferAfter, Size) :- 
            length(BufferBefore, BuffSize), BuffSize < Size, !, 
            car(DataBefore, Elem), 
            addlast(Elem, BufferBefore, BufferAfter), 
            deletefirst(DataBefore, DataAfter).
    

    几个跑步的例子

    consumer([1,2,3,4,5], BufferAfter, Result) 
    

    返回

    BufferAfter = [2,3,4,5], Result = 1.
    

    producer([1,2,3,4,5,6],[7,8,9],DataAfter, BufferAfter, %">3 here"%) 
    

    返回

    DataAfrer = [2,3,4,5,6], BufferAfter = [7,8,9,1].
    

    现在,为了演示任何计算,我们需要编写一个程序,它将运行“消费者”直到缓冲区为空。当缓冲区为空时,“消费者”将运行“生产者”。并停止进程,当数据和缓冲区为空时。 希望对任何人都有用。

    【讨论】:

      猜你喜欢
      • 2016-06-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-09-26
      • 2022-11-14
      • 2019-06-08
      相关资源
      最近更新 更多