Turbo Prolog 2.0 中的循环缓冲区

发布于 2024-11-10 07:23:13 字数 76 浏览 0 评论 0原文

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

I need to write something like circular buffer in TurboProlog 2.0 for calculating average. I don't know what predicates i need to write, and have no idea how link them together.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

叫思念不要吵 2024-11-17 07:23:13

我不确定您的应用程序需要实现“循环缓冲区”的哪些功能。一般来说,“缓冲区”是可重用的存储,通常与处理异步通信的 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 还支持具有一些附加功能的“外部”事实库,外部是指以允许持久性和扩展空间超出为内部事实库分配的空间的方式存储(在内存中或磁盘上)。考虑到通常与循环缓冲区相关的适度固定大小(因为它们是为了重用,并且通常通过阻塞输入进程直到输出进程有机会赶上来处理溢出),外部事实库似乎没有提供太多有趣的是,持久“缓冲区”的能力可能对长时间运行的进程感兴趣。

希望这些建议能够澄清这里真正需要完成的事情。

I'm not sure what functionality of "a circular buffer" needs to be realized for your application. In general a "buffer" would be reusable storage, often associated with I/O processes that handle asynchronous communications (hence the need for a buffer that allows one process to get ahead of the other). A "circular buffer" denotes a way of managing the available storage with pointers (both to the beginning and end of valid/unprocessed data) that wraparound through a (linear) contiguous region. This has an advantage over maintaining a FIFO queue with a fixed location for the beginning of valid data because no "shuffling" of unprocessed items is required.

In the general context of standard Prolog, where rewriting memory locations is not directly supported, that advantage doesn't make sense. Even in Turbo Prolog it has to be asked exactly what you want to accomplish, so that a skillful use of the extended/nonstandard features available can be made.

Here are some ideas:

  1. Turbo Prolog supports lists that are in some ways more restrictive and perhaps in other ways more elaborate than the proper lists of standard Prolog. One of the restrictions is that in Turbo Prolog all items of a list must belong to the same "domain", a notion foreign to the weakly-typed character of standard Prolog. Also domains may be designated as "reference" domains in Turbo Prolog, a level of indirection that permits partially bound compound terms to be passed between subgoals. Without going into too much detail, one sense of "circular buffer" might be a "list" (formed from a reference domain) which wraps back around on itself (a cyclical reference). Such a term can be created in many other Prologs, the distinction being that it is not a proper list. Circular though such a term might be, it would not be much of a buffer (once created) because items in the list could not be rewritten.

  2. Turbo Prolog supports dynamic assertion and retraction of facts, with metapredicates like asserta/1 and assertz/1 that allow serial positioning of new facts at the beginning or the end of those existing facts for the same predicate (and also if desired within a specified named "module" or factbase to use the Turbo Prolog terminology). If the simple management of items in a FIFO queue is your objective, then this is most likely the approach you want (at least for an initial implementation), with items encapsulated as facts.

  3. Turbo Prolog also supports "external" factbases with some additional features, external in the sense of being stored (either in memory or on disk) in a way that allows persistence and expanded space beyond what is allocated for internal factbases. Given the modest fixed sizes usually associated with circular buffers (because they are meant for reuse and overflow is usually dealt with by blocking on the input process until the output process has a chance to catch up), external factbases don't seem to offer much of interest, though possibly the ability to persist "buffers" might be of interest for long-running processes.

Hopefully these suggestions will elicit some clarification on what really needs to be accomplished here.

酒中人 2024-11-17 07:23:13

经过深思熟虑,编写了以下程序

% 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].

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

After much thought, was written the following program

% 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).

Several examples of running

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

returns

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

And

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

returns

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

Now, to demonstrate any calculation, we need to write a program that, which will run "consumer" until the buffer is empty will be. And "consumer" will run "producer", when buffer is empty. And stop the process, when data and buffer will be empty.
Hope will be useful to anyone.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文