{"id":23640986,"url":"https://github.com/pedromsilvapt/zitt","last_synced_at":"2025-08-31T17:32:16.747Z","repository":{"id":142836446,"uuid":"375504280","full_name":"pedromsilvapt/zitt","owner":"pedromsilvapt","description":"Experimental Zig chainable iterators library","archived":false,"fork":false,"pushed_at":"2021-06-29T21:45:33.000Z","size":26,"stargazers_count":6,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2023-10-20T22:18:04.955Z","etag":null,"topics":["functional-programming","iterators","streams","zig"],"latest_commit_sha":null,"homepage":"","language":"Zig","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/pedromsilvapt.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null}},"created_at":"2021-06-09T22:27:29.000Z","updated_at":"2023-10-20T22:18:08.282Z","dependencies_parsed_at":"2023-06-04T23:15:30.609Z","dependency_job_id":null,"html_url":"https://github.com/pedromsilvapt/zitt","commit_stats":null,"previous_names":[],"tags_count":0,"template":null,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pedromsilvapt%2Fzitt","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pedromsilvapt%2Fzitt/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pedromsilvapt%2Fzitt/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pedromsilvapt%2Fzitt/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/pedromsilvapt","download_url":"https://codeload.github.com/pedromsilvapt/zitt/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":231610637,"owners_count":18400207,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["functional-programming","iterators","streams","zig"],"created_at":"2024-12-28T09:53:46.234Z","updated_at":"2024-12-28T09:53:46.673Z","avatar_url":"https://github.com/pedromsilvapt.png","language":"Zig","funding_links":[],"categories":[],"sub_categories":[],"readme":"# zitt\nThis repository contains an experimental iterator repository. Native iterators \nin Zig are considered by this library as any structure that provides a `next` \nmethod and that returns an optional.\n\nThis library provides a function `itt` that can be used to wrap any array, \nslice or native iterator into a chainable iterator. A Chainable Iterator also\nhas a method `next`, like native iterators, but provides a wealth of other base \nchainable operators such as `map`, `filter`, etc...\n\nThe library also provides a pretty straightforward way to allow the user to\ninclude his own custom iterator operators and use them the same way as base\noperators.\n\n## Requirements\n - Zig v0.8\n\n## Usage\n```zig\nconst std = @import(\"std\");\nconst expect = std.testing.expect;\nconst itt = @import(\"zitt\");\n\ntest {\n    var array = [_]Number{\n        Number{ .value = 1 },\n        Number{ .value = 2 },\n        Number{ .value = 3 },\n    };\n\n    var iter = itt.from(array)\n        .mapField(.value)\n        .map(square)\n        .mapCtx(add, @as(i32, 2));\n\n    try expect(iter.next().? == 3);\n    try expect(iter.next().? == 6);\n    try expect(iter.next().? == 11);\n    try expect(iter.next() == null);\n}\n\n// Helper Declarations\npub const Number = struct { value: i32 };\n\npub fn square(number: i32) i32 {\n    return number * number;\n}\n\npub fn add(constant: i32, number: i32) i32 {\n    return constant + number;\n}\n```\n\n## Custom Operators\n```zig\nconst IttGeneric = @import(\"zitt\").IttGeneric;\nconst meta = @import(\"zitt\").meta;\n\n/// First we need to create a new operator. Usually each operator can have one\n/// or more chainable functions (in this case, one called `take`) and a \n/// Chainable Iterator that is returned by calling the operator function.\nfn MyCustomTakeOperator(comptime Itt: type) type {\n    return struct {\n        pub fn take(self: Itt, number: usize) Iterator {\n            return Iterator{ .source = self, .number = number };\n        }\n\n        /// Note that this is not public, because we do not want this declaration\n        /// being available after calling itt, like `itt(...).Iterable`\n        /// If we want our iterable to be accessible to the outside world, we can\n        /// declare it as a generic function outside the operator\n        const Iterator = struct {\n            /// The iterator almost always has the field `source: Itt`, followed\n            /// by the operator-specific fields.\n            source: Itt,\n            number: usize,\n            consumed: usize = 0,\n\n            /// Each chainable iterator also needs this as a public declaration\n            /// This is the type of the source iterator that this operator was built for\n            pub const Source = Itt;\n\n            /// The final piece required of each iterator is, of course, the\n            /// `next` method. It should always receive only a pointer to itself,\n            /// and return an optional Elem\n            pub fn next(self: *Iterator) meta.AutoReturn(Itt.ErrorSet, ?Itt.Elem) {\n                if (self.consumed \u003c self.number) {\n                    self.consumed += 1;\n\n                    // Note that if our `self.number` is bigger than the amount\n                    // of elements in the source iterator, we are going to be\n                    // calling `source.next` multiple times after the iterator\n                    // has been exhausted/emptied. This is fine because all\n                    // iterators should return null all the time after being\n                    // emptied, and in this case we can take advantage of that\n                    return if (Itt.ErrorSet != null)\n                        try self.source.next()\n                    else\n                        self.source.next();\n                }\n\n                return null;\n            }\n\n            /// Finally, we need to import our utility IttGeneric, by passing\n            /// operators currently being used, as well as this very own\n            /// iterator type. This is what allows all operators to be chainable\n            pub usingnamespace IttGeneric(Itt.Operators, Iterator);\n        };\n    };\n}\n\n// Then we can, on the ***root Zig file* of our application, declare a public function\n// to include our custom operator method. This function should return a struct,\n// where every declaration of this struct will be available in the chainable iterators\npub fn IttCustomOperators(comptime Itt: type) type {\n    return struct {\n        pub usingnamespace MyCustomTakeOperator(Itt);\n    };\n}\n\n// An alternative to this approach is to use the IttFactory\n// This gives us more customization options, such as being able to use\n// different operators in different situations, or even not including the base\n// operators\nconst IttFactory = @import(\"zitt\").IttFactory;\nconst IttBaseOperators = @import(\"zitt\").IttBaseOperators;\nconst IttBaseGenerators = @import(\"zitt\").IttBaseGenerators;\n\n/// This function merges the base operators as well as our custom operator\n/// Note that this is a generic function, just like our operator. This is \n/// because all operators are instanced for every type of source operator they\n/// are called for. This has some neat advantages, such as being able to declare\n/// different operators for different sources (for example, have a `sum()` be\n/// available only for cases when Itt.Elem is a numeric type).\nfn IttCustomLocalOperators(comptime Itt: type) type {\n    return struct {\n        pub usingnamespace IttBaseOperators(Itt);\n        pub usingnamespace MyCustomTakeOperator(Itt);\n    };\n}\n\n/// Create the wrapper function, by giving it the operators\nconst custom_itt = IttFactory(IttCustomLocalOperators, IttBaseGenerators);\n\ntest {\n    var array = [_]Number{\n        Number{ .value = 1 },\n        Number{ .value = 2 },\n        Number{ .value = 3 },\n    };\n\n    var iter = custom_itt.from(array)\n        .take(2);\n\n    try expect(iter.next().?.value == 1);\n    try expect(iter.next().?.value == 2);\n    try expect(iter.next() == null);\n}\n```\n\n## Architecture\nRight now this library is pretty comptime heavy, I figure, and honestly I'm not \nyet sure if it is a lucky stroke of genius or a Frankenstein-like work.\n\nRegardless, if you've got any comments or suggestions for it, please do\nlet me know! :)\n\n## Building/Testing\nTo build and/or run the tests, just execute either of the following commands:\n```bash\nzig build\nzig build test\n```","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpedromsilvapt%2Fzitt","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpedromsilvapt%2Fzitt","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpedromsilvapt%2Fzitt/lists"}