d的opnext

原文
我发现empty/front/popNext协议在一般(至少在Weka代码库中)非常麻烦,人们更喜欢opApply(尽管有自己的问题).
今天甚至遇见了使用现有协议无法解决问题:如果foreach中断了,消费区间(比如文件流)不应消费.使用opApply,这很容易(闭包返回非零值),但是使用popNext,这很难.我不详细讨论细节,所以直接跳到建议的协议.

bool opNext(out T elem) {...}

如果"产生"了一个元素,下个(opNext)操作,则返回true,如果到达了结尾,则返回false.

foreach (elem; range) {
    ...
}

只是降级到

T elem;
while (range.opNext(elem)) {
   ...
}

当然,该协议可与现有协议并存,只是在降级规则中优先.具体示例:

struct LinkedList {
    int value;
    LinkedList* next;

    struct Range {
        LinkedList* cursor;

        bool opNext(out int val) nothrow @nogc {
            if (cursor is null) {
                return false;
            }
            val = cursor.value;
            return true;
        }
    }

    auto members() {return Range(&this);}
}

foreach (val; myList.members) {
    ...
}

注意:
0,对新协议也可用保存()/save(),它只需要复制迭代器的状态.
1,也许加上opPrev来搞定双向区间是可行的,但,用途不大.
2,在新协议中更容易链接map/filter/etc

出于好奇:你认为,对比如下,其优缺点:

Option!(T) opNext() { ... }

选项(Option)选项类型实现,因此包含了是否产生元素问题.这是简化/重新设计区间概念的另一个建议.)
基于选项设计的优点是不需要持久的前(front),更适合(如,从中读的)真输入区间.
方法有可引用持久底层数据,这可能更加笨拙.

mixin template NextToRange(ElementType) {
    ElementType _value;
    bool _haveValue;

    @property {
        bool empty() {
            return !_haveValue;
        }

        ElementType front() {
            assert(_haveValue);
            return _value;
        }
    }

    void popFront() {
        _haveValue = nextValue(_value);
    }
}

不需要破坏很大比例标准库就可使用它;).

posted @   zjh6  阅读(12)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示