Interface 基于流的D语言范围块处理

Interface 基于流的D语言范围块处理,interface,stream,block,d,monads,Interface,Stream,Block,D,Monads,我正在寻找一种优雅的方式来执行基于数据流的块 数组/范围的处理。我正在建立一个文件索引/搜索 D中的引擎,用于计算文件的各种统计信息 例如直方图和SHA1摘要。我希望这些计算能够 就数据访问而言,可一次性执行 地点 以下是发动机的摘录 /** Process File in Cache Friendly Chunks. */ void calculateCStatInChunks(immutable (ubyte[]) src, size_

我正在寻找一种优雅的方式来执行基于数据流的块 数组/范围的处理。我正在建立一个文件索引/搜索 D中的引擎,用于计算文件的各种统计信息 例如直方图和SHA1摘要。我希望这些计算能够 就数据访问而言,可一次性执行 地点

以下是发动机的摘录

/** Process File in Cache Friendly Chunks. */
void calculateCStatInChunks(immutable (ubyte[]) src,
                            size_t chunkSize, bool doSHA1, bool doBHist8) {
    if (!_cstat.contentsDigest[].allZeros) { doSHA1 = false; }
    if (!_cstat.bhist8.allZeros) { doBHist8 = false; }

    import std.digest.sha;
    SHA1 sha1;
    if (doSHA1) { sha1.start(); }

    import std.range: chunks;
    foreach (chunk; src.chunks(chunkSize)) {
        if (doSHA1) { sha1.put(chunk); }
        if (doBHist8) { /*...*/ }
    }

    if (doSHA1) {
        _cstat.contentsDigest = sha1.finish();
    }
}
似乎这不是一种非常优雅的(功能性)方法,因为我必须在代码中的三个不同位置为每个统计数据(缩减器)分配逻辑,即
start
put
finish


有没有人对Haskell monad之类的基于流的API有什么建议/参考,可以使代码更加基于D风格的组件?

我没有Haskell方面的经验,但是,请让我分享一下我在D中的做法。也许这会有一些用处

首先,我发现

if (!_cstat.contentsDigest[].allZeros) { doSHA1 = false; } if (!_cstat.bhist8.allZeros) { doBHist8 = false; }
你的代码中有一个bug。SHA1是一种值类型。如果您通过值将其传递给calculateInChunks,则main中的值将永远不会更新,并且您看到的哈希与从未向其添加数据的哈希相同。一种解决方案是在主函数中传递指向sha1的指针。它也应该与“ref”一起使用,但是元组上的ref似乎不起作用?无论如何,我可能会禁用摘要结构的隐式复制,以便在编译时捕获这些问题。(其实我早就想这么做了,后来就忘了)。顺便说一句:有了makeDigest:通过一些重构,我们得到了这样一个结论:像copyToMany这样的东西应该是火卫一的一部分,但是自己编写也很容易。 _cstat.contentsDigest = sha1.finish();
import std.digest.sha;
import std.stdio;
import std.algorithm;

void copyToMany(R, T...)(R src, T target)
{
    foreach(element; src)
    {
        foreach(s; target)
            s.put(element);
    }
}

void main()
{
    import std.range: chunks;

    auto input = (cast(immutable (ubyte[]))[1, 2, 3]).chunks(2);

    SHA1 sha1 = makeDigest!SHA1();
    auto reducer = new Reducer!(0, (a,b) => a + b);

    input.copyToMany(&sha1, reducer);

    writeln(sha1.finish().toHexString());
    writeln(reducer.result);
}



class Reducer(alias init, alias Func)
{
    typeof(init) result = init;

    void put(R)(R r) {
        foreach (e; r)
        {
            result = Func(result, e);
        }
    }
}