{"id":42333851,"url":"https://github.com/haxetink/tink_streams","last_synced_at":"2026-01-27T14:10:29.683Z","repository":{"id":54531671,"uuid":"46568679","full_name":"haxetink/tink_streams","owner":"haxetink","description":"Streams from the future. With lasers, of course ... whoaaaaa!!!!","archived":false,"fork":false,"pushed_at":"2024-06-27T11:22:11.000Z","size":200,"stargazers_count":12,"open_issues_count":6,"forks_count":9,"subscribers_count":5,"default_branch":"master","last_synced_at":"2024-06-27T16:07:40.404Z","etag":null,"topics":["data","gadt","haxe","immutable","streams","tink"],"latest_commit_sha":null,"homepage":null,"language":"Haxe","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"unlicense","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/haxetink.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2015-11-20T15:05:05.000Z","updated_at":"2023-04-11T15:18:23.000Z","dependencies_parsed_at":"2024-02-02T16:42:34.713Z","dependency_job_id":"8c27fb48-036b-4698-8235-2bb10b1ac0ba","html_url":"https://github.com/haxetink/tink_streams","commit_stats":null,"previous_names":[],"tags_count":9,"template":false,"template_full_name":null,"purl":"pkg:github/haxetink/tink_streams","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/haxetink%2Ftink_streams","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/haxetink%2Ftink_streams/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/haxetink%2Ftink_streams/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/haxetink%2Ftink_streams/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/haxetink","download_url":"https://codeload.github.com/haxetink/tink_streams/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/haxetink%2Ftink_streams/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28814452,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-27T12:25:15.069Z","status":"ssl_error","status_checked_at":"2026-01-27T12:25:05.297Z","response_time":168,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"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":["data","gadt","haxe","immutable","streams","tink"],"created_at":"2026-01-27T14:10:29.115Z","updated_at":"2026-01-27T14:10:29.670Z","avatar_url":"https://github.com/haxetink.png","language":"Haxe","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Tinkerbell Streams\n\n[![Build Status](https://travis-ci.org/haxetink/tink_streams.svg?branch=master)](https://travis-ci.org/haxetink/tink_streams)\n[![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/haxetink/public)\n\nThis library provides immutable streams, which are vaguely similar to iterators but might more accurately be thought of as immutable asynchronous lazy lists. Progressing along a stream yields a new stream instead modifying the original. The data in a stream is generated *as needed*.\n\nBecause the world is a harsh place, we must discern \"real\" streams from \"ideal\" streams, where the former may yield errors, while the latter will not. To deal with this distinction, `tink_streams` makes relatively strong use of [GADTs](http://code.haxe.org/category/functional-programming/enum-gadt.html), a somewhat arcane feature of Haxe. \n\nIn a nutshell, the distinction is expressed like so:\n  \n```haxe\ntypedef RealStream\u003cItem\u003e = Stream\u003cItem, Error\u003e;\ntypedef IdealStream\u003cItem\u003e = Stream\u003cItem, Noise\u003e;\n```\n\nSo a \"real stream of items\" is a \"stream of items with errors\", while an \"ideal stream of items\" is a \"stream of items with nothing\" (in tinkerbell `Noise` is used to express nothingness, because of the limitations `Void` exhibits). So let's have a look at what a stream looks like and how we can operate on it:\n\n```haxe\nabstract Stream\u003cItem, Quality\u003e {\n  function forEach\u003cSafety\u003e(handle:Handler\u003cItem, Safety\u003e):Future\u003cConclusion\u003cItem, Safety, Quality\u003e\u003e;\n}\n\ntypedef Handler\u003cItem, Safety\u003e = Item-\u003eFuture\u003cHandled\u003cSafety\u003e\u003e;\n\nenum Handled\u003cSafety\u003e {\n  BackOff:Handled\u003cSafety\u003e;\n  Finish:Handled\u003cSafety\u003e;\n  Resume:Handled\u003cSafety\u003e;\n  Clog(e:Error):Handled\u003cError\u003e;\n}\n\nenum Conclusion\u003cItem, Safety, Quality\u003e {\n  Halted(rest:Stream\u003cItem, Quality\u003e):Conclusion\u003cItem, Safety, Quality\u003e;\n  Clogged(error:Error, at:Stream\u003cItem, Quality\u003e):Conclusion\u003cItem, Error, Quality\u003e;\n  Failed(error:Error):Conclusion\u003cItem, Safety, Error\u003e;\n  Depleted:Conclusion\u003cItem, Safety, Quality\u003e;\n}\n```\n\nDon't let this zoo of type parameters irritate you. They all have their place and we actually know two of them already: `Item` denotes the type of items that flow through the stream and `Quality` is what we use to draw the line between ideal and real streams.\n\nThere are many more functions defined on streams, but `forEach` is by far the most important one. As we see it accepts a handler for `Item` with a certain `Safety`. This is to allow us to differentiate ideal and real handlers (although we don't explicitly define them). A handler is a function that gets an item and then tells us how it has handled it. It can either `BackOff`, thus stopping iteration *before* that item, or `Finish` this stopping iteration *after* that item, it can `Resume` the iteration or - if it is a `Handler\u003cItem, Error\u003e` - it may `Clog`.\n\nIteration can be concluded for various reasons which are thus expressed in the `Conclusion` enum, which handles four cases:\n  \n- `Halted`: the handler stopped the iteration. The `rest` then represent the remaining stream. So if the handler returns `BackOff` the first item of the remaining stream will be the last item the handler treated, otherwise it's all the items that would have been passed to the handler, had it not stopped.\n- `Clogged`: the handler raised an `error` and `at` is the remaining stream (including the item where the error was raised)\n- `Failed`: the stream failed. Note that no remaining stream is given, because when streams fail, they end.\n- `Depleted`: the whole stream was used up. Therefore this case also has no remaining stream.\n\nIf the stream is ideal (and thus `Quality` is not `Error`), then `Failed` is unexpected, if the handler is ideal (and thus `Safety` is not `Error`), then `Clogged` is unexpected.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhaxetink%2Ftink_streams","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhaxetink%2Ftink_streams","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhaxetink%2Ftink_streams/lists"}