gpt4 book ai didi

d - D 中 OutputRange 和 put() 的目的是什么?

转载 作者:行者123 更新时间:2023-12-02 00:11:00 25 4
gpt4 key购买 nike

我需要对 OutputRange 及其用途进行一些说明。它表示类似于发送到 stdout 的流式元素输出,并且需要支持 put() 方法,该方法:

determines the capabilities of the range and the element at compile time and uses the most appropriate method to output the element.

输出 元素,但到哪里 以及什么目的

import std.stdio;
import std.range;

void main() {
int[] arr = [1, 2, 3, 4, 5];
auto s = arr;
writeln(s); // [1, 2, 3, 4, 5]
s.put(100); // nothing is printed to stdout, should it?
writeln(s); // [2, 3, 4, 5]
}

在上面的代码中,我们在切片上调用了 put(),因此我们丢失了 1,但是“100”去了哪里? MultiFile这个例子感觉有点做作。 OutputRange 的更实用的用例会更好。

一件小事,put为什么叫put?在其他语言中,put 用于对某些集合进行插入或添加操作。我觉得很困惑。

更新:看起来我们需要保留原始切片的副本以防止元素丢失。

int[] arr = [1, 2, 3, 4, 5];
auto s = arr;
s.put(100);
writeln(arr); // [100, 2, 3, 4 ,5];

我发现上面的内容很困惑,也许我错过了 OutputRange 背后的概念 :(

最佳答案

首先,阅读put的文档:http://dpldocs.info/experimental-docs/std.range.primitives.put.html

值得注意的是:

Tip: put should not be used "UFCS-style", e.g. r.put(e). Doing this may call R.put directly, by-passing any transformation feature provided by Range.put. put(r, e) is prefered.

所以不要调用s.put(x),而是调用put(s, x);

它还讨论了您的更新中发生的事情:

put treats dynamic arrays as array slices, and will call popFront on the slice after an element has been copied.

Be sure to save the position of the array before calling put.

您还会注意到文档经常使用“复制”一词。那么,put 将项目放在哪里,为什么?

在哪里 取决于输出范围。 put 是一个通用接口(interface),可以根据目标对象执行各种操作。有些人可能会将其流式传输到标准输出,有些人可能会将其放入数据缓冲区,有些人可能会做一些完全不同的事情。

在您使用的数组切片的情况下,库将其解释为固定大小的缓冲区,并且其put 将数据复制到其中。

实现看起来像

copy element to buffer
advance buffer
update buffer's remaining space

这就是为什么您需要在开头保留对切片的单独引用,否则它会复制并前进,所以它看起来就像消失了一样。为什么它会这样做?

int[32] originalBuffer;
int[] buffer = originalBuffer[];
put(buffer, 5);
put(buffer, 6); // since the last one advanced the remaining space, this next call just works

最后实际使用了多少缓冲区?这是前进的另一个用途:你可以减去它:

int[] usedBuffer = originalBuffer[0 .. $ - buffer.length];

我们只取出原始文件中的所有内容,除了剩余的内容作为输出范围中的剩余空间。

其他范围可能会保留内部计数。 http://dpldocs.info/experimental-docs/std.range.primitives.put.html#examples 处的文档示例显示了一个带有动态内部缓冲区的示例。

static struct A {
string data;
void put(C)(C c) if (isSomeChar!C) {
data ~= c;
}
}

它的 put 方法将字符复制到一个内部字符串中,因此它会根据需要增长,然后 data.length 告诉您它有多大。 (stdlib 的 appender 就像这样顺便说一句)

输出范围接口(interface)非常小 - 它真正需要的只是一个 put 函数,然后它没有指定你用它做什么。想象一下,如果它正在写入 stdout,那么长度无关紧要,根本不需要将数据返回给用户。这也是它不使用 ~= 附加运算符的原因 - 它不一定附加任何内容。


所以回顾一下:它去了哪里,为什么?视对象而定! OutputRange/put 是经过深思熟虑的通用接口(interface),旨在收集数据并用它来做……一些事情。它是一个最终目的地,因此不支持像其他范围一样的链接。

使用内置切片,它会向其中复制数据并提升位置以使其准备好接受更多数据。这需要你做更多的工作来跟踪它,但为通用使用提供了很大的灵 active 和效率。尽管专门针对您的特定需求,但您可能会更好地使用其他功能。如果要附加,请尝试 http://dpldocs.info/appender例如。

关于d - D 中 OutputRange 和 put() 的目的是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59115028/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com