D中OutputRange和put()的用途是什么?

D中OutputRange和put()的用途是什么?,d,D,我需要一些关于输出范围及其用途的说明。它表示流元素输出,类似于发送到标准输出,需要支持put()方法,该方法: 在编译时确定范围和元素的功能,并使用最合适的方法输出元素 将元素输出到的何处,用于什么目的 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(1

我需要一些关于输出范围及其用途的说明。它表示流元素输出,类似于发送到标准输出,需要支持
put()
方法,该方法:

在编译时确定范围和元素的功能,并使用最合适的方法输出元素

将元素输出到的何处,用于什么目的

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”去了哪里?这个例子有点做作。
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
的文档:

值得注意的是:

提示:put不应使用“UFCS风格”,例如r.put(e)。这样做可能会通过传递Range提供的任何转换功能直接调用r.put。put(r,e)是首选

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

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

put将动态数组视为数组切片,并在复制元素后调用切片上的popFront

在调用put之前,请确保保存数组的位置

你也会注意到文档经常使用“复制”这个词。那么,
把项目放在哪里,为什么

Where取决于输出范围。
put
是一个通用接口,可以根据目标对象执行各种操作。有些可以将其流式传输到stdout,有些可以将其放入数据缓冲区,有些可以执行完全不同的操作

对于您正在使用的数组片,库将其解释为固定大小的缓冲区,其
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];
除了输出范围内的剩余空间,我们只需要从原始文件中提取所有内容

其他范围可能保留一个内部计数。的文档示例显示了一个具有动态内部缓冲区的示例

static struct A {
    string data;
    void put(C)(C c) if (isSomeChar!C) {
        data ~= c;
    }
}
它的
put
方法将字符复制到一个内部字符串中,因此它将根据需要增长,然后
数据。length
告诉您它有多大。(stdlib的
appender
工作原理与此类似)

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


概括一下:它去哪里了?为什么?取决于对象!OutputRange/put是经过深思熟虑的通用接口,旨在收集数据并对其进行处理。它是最终目的地,因此不支持与其他范围一样的链接

使用内置切片,它可以将数据复制到切片中,并提升位置,使其随时准备接受更多数据。这需要您的终端做更多的工作来跟踪数据,但为通用使用提供了很大的灵活性和效率。尽管专门针对您的特定需要,您可能会更好地使用其他功能。如果您愿意的话要追加,请尝试例如