Interface struct ‣ Iterator - chung-leong/zigar GitHub Wiki

JavaScript | PHP


When a struct contains a next function, it'll be treated as an iterator. Zigar will automatically calls this function when you place the struct in a for-of loop:

const Range = struct {
    current: i32,
    end: i32,

    pub fn next(self: *@This()) ?i32 {
        if (self.current < self.end) {
            const value = self.current;
            self.current += 1;
            return value;
        } else {
            return null;
        }
    }
};

pub fn range(start: i32, end: i32) Range {
    return .{ .current = start, .end = end };
}
import { range } from './iterator-1.zig';

for (const value of range(3, 8)) {
    console.log(value);
}
3
4
5
6
7

next should accept a non-const pointer to the struct as its first argument. It should return an optional value. It must also be public. If you forget to place pub at the front of the function declaration, the struct will behave like a normal struct:

const Range = struct {
    current: i32,
    end: i32,

    fn next(self: *@This()) ?i32 {
        if (self.current < self.end) {
            const value = self.current;
            self.current += 1;
            return value;
        } else {
            return null;
        }
    }
};

pub fn range(start: i32, end: i32) Range {
    return .{ .current = start, .end = end };
}
import { range } from './iterator-2.zig';

for (const value of range(3, 8)) {
    console.log(value);
}
[ 'current', 3 ]
[ 'end', 8 ]

It can receive std.mem.Allocator as its second argument for values that require memory allocation:

const std = @import("std");

const Range = struct {
    current: i32,
    end: i32,

    pub fn next(self: *@This(), allocator: std.mem.Allocator) !?[]u8 {
        if (self.current < self.end) {
            defer self.current += 1;
            return try std.fmt.allocPrint(allocator, "{b}", .{self.current});
        } else {
            return null;
        }
    }
};

pub fn range(start: i32, end: i32) Range {
    return .{ .current = start, .end = end };
}
import { range } from './iterator-example-3.zig';

for (const value of range(3, 8)) {
    console.log(value.string);
}
11
100
101
110
111

Interface structs | Generator