Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

An iterator interface

Emulating interfaces by providing an implementation and overriding functions.

const std = @import("std");

const IteratorImplementation = struct {
    containerType: type,
    valueType: type,
    baseImpl: type,
};

fn Iterator(implementation: IteratorImplementation) type {
    const containerType = implementation.containerType;
    const valueType = implementation.valueType;
    const baseImpl = implementation.baseImpl;
    return struct {
        const next = baseImpl.next;
        const sum = if (@hasDecl(baseImpl, "sum")) baseImpl.sum else (struct {
            fn impl(it: *containerType) valueType {
                var res: valueType = 0;
                while (next(it)) |val| {
                    res += val;
                }
                return res;
            }
        }).impl;
    };
}

test "Iterator" {
    const MyImpl = Iterator(.{
        .containerType = []const f64,
        .valueType = f64,
        .baseImpl = struct {
            fn next(it: *[]const f64) ?f64 {
                if (it.*.len == 0) {
                    return null;
                } else {
                    defer it.* = it.*[1..];
                    return it.*[0];
                }
            }
        },
    });

    var x: []const f64 = &.{ 3.141, 1.0, -42.0 };

    std.debug.print("{}\n", .{MyImpl.sum(&x)});
}

Test with: zig test iter.zig

$ zig test iter.zig
-37.859
All 1 tests passed.
Last change: , commit: ffe1a9c