{"id":15642038,"url":"https://github.com/knutwalker/transducers-scala","last_synced_at":"2025-04-30T09:24:01.272Z","repository":{"id":22502128,"uuid":"25841712","full_name":"knutwalker/transducers-scala","owner":"knutwalker","description":"Transducers are a way to build reusable transformations.","archived":false,"fork":false,"pushed_at":"2018-04-04T18:43:45.000Z","size":1493,"stargazers_count":66,"open_issues_count":3,"forks_count":1,"subscribers_count":8,"default_branch":"master","last_synced_at":"2025-04-26T23:16:52.082Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Scala","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/knutwalker.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}},"created_at":"2014-10-27T22:14:43.000Z","updated_at":"2022-07-03T16:47:31.000Z","dependencies_parsed_at":"2022-07-12T06:16:08.666Z","dependency_job_id":null,"html_url":"https://github.com/knutwalker/transducers-scala","commit_stats":null,"previous_names":[],"tags_count":9,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/knutwalker%2Ftransducers-scala","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/knutwalker%2Ftransducers-scala/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/knutwalker%2Ftransducers-scala/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/knutwalker%2Ftransducers-scala/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/knutwalker","download_url":"https://codeload.github.com/knutwalker/transducers-scala/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":251675334,"owners_count":21625792,"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":[],"created_at":"2024-10-03T11:53:48.047Z","updated_at":"2025-04-30T09:24:01.249Z","avatar_url":"https://github.com/knutwalker.png","language":"Scala","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![Build Status][ci-img]][ci]\n[![Coverage][coverage-img]][coverage]\n[![Maven][maven-img]][maven]\n[![Apache License][license-img]][license]\n\n# transducers-scala\n\nTransducers are a way to build reusable transformations.\n\nPut simply, transducers are like operations on collections (e.g. `map` and `filter`)\nbut without being bound to any collection or result type. Thus, they can be reused\nin many contexts and carry only the simple processing logic.\n\n## Getting it\n\n`transducers-scala` is published to sonatype:\n\n```scala\nlibraryDependencies += \"de.knutwalker\" %% \"transducers-scala\" % \"0.5.0\"\n```\n\nDetailed instructions are available [the installation notes][install].\n\n### Snapshot version\n\nA snapshot is available at sonatype:\n\n```scala\nresolvers += \"sonatype snapshots\" at \"https://oss.sonatype.org/content/repositories/snapshots/\"\n\nlibraryDependencies += \"de.knutwalker\" %% \"transducers-scala\" % \"0.6.0-SNAPSHOT\"\n```\n\n\nAlternatively, clone this repo and run\n\n```bash\n./sbt +publishLocal # for ivy-style repositories\n./sbt +publishM2    # for maven-style repositories\n```\n\n\n## Using it\n\nAdd `\"de.knutwalker\" %% \"transducers-scala\" % \"0.5.0\"` to your dependencies.\nThe full artifact names are `transducers-scala_2.10` and `transducers-scala_2.11`, so\nthis library is available for Scala 2.10 and 2.11.\n\nAfter that, simply use `scalax.transducers._`\n\n```scala\nimport scalax.transducers._\n\nval xform = filter[Int](_ % 2 == 0).map(_.toString).flatMap(_.toList).take(10)\nval data = Stream.from(13)\nval result = into[List].run(xform)(data)\nassert(result == List('1', '4', '1', '6', '1', '8', '2', '0', '2', '2'))\n```\n\nFor more examples and a better introduction, see the [Usage Guide][usage].\n\n\n## Explanation\n\nIn short, transducers transform reducers.\nReducers combine some result and a value together to a new result.\nReducers are similar to the binary operations, one uses with folds.\nA Transducer takes a reducer and return a transformed reducer.\nThe crux is, that neither reducers nor transducers are in any form aware of their concrete\ninput and output types.\n\n#### Type simplification\n\n```scala\ntype Reducer[A, R] = ((R, A) =\u003e R)\n\ntype Transducer[A, B] = (Reducer[B, R] =\u003e Reducer[A, R]) forSome { type R }\n```\n\nReducers are just functions, that combine a result and an input value to a new result.\nThis implementation is restricted in such a way, that the `R` is identical (same `R` in and out).\nThis is mostly not a problem, since transducers may change types and most reducers have access\nto a down-stream reducer of the target type (that can be different from `A`).\nReducers also have two additional operations.\nThe first is a setup operation, that is called with the current result before\nand items flow through the reducer.\nThe second is a finish operation, that allows the reducer to do something whenever a stream of data is finished (although it might never finish).\n\nA `Transducer[A, B]` is a function, that takes an `Reducer[B, _]` and returns an `Reducer[A, _]`.\nTransducers transform their reducers from right to left. When finally applied, the data flows\nfrom left to right. So, a `Transducer[A, B]` can roughly be seen as a function `A =\u003e B`, in that\nit describes a transformation from `A` to `B`, but it is not specified, how many `B` can be produced.\nA transducer may provide 0, 1, or an arbitrary number of `B`s, not just one (as `A =\u003e B` would have to).\n\nAn important note is, that `Transducer[A, B]` is a rank-2 type to quantify `R` without\nneeding to know about it. This makes transducers completely unaware of their input or output.\n\n\n## Some other projects with partially similar traits\n\nBesides [Clojure](http://clojure.org/) and [transducers-java][transducers-java]\nthere exist a number of projects, that share some traits with `transducers-scala`.\n\n### RxJava (RsScala)\n\nProbably the most similar concept are RxJava's Operators.\nOperators transform Subscribers where transducers transform reducers.\nWhile these operators are bound to be used with Subscribers, the Subscriber/Observer/Observable\nitself can be plugged in easily on different sources and targets.\n\n### psp-view (psp-std)\n\nPaul Phillips'\n[take on a scala collection/standard library][psp-std]\nincludes collections, that are thoroughly non-strict and thus, achieve the same traits on terms of\nlaziness and early termination. These are, however, regular collections where the operations are\nbound to the specific collection.\n\n\n## Acknowledgement\n\nThis stuff is build on top of Rich Hickeys transducers for Clojure and Java.\nSee [this talk][transducers-yt] and [this post][transducers-blog] for more info.\nAlso, there is a [Java implementation][transducers-java].\n\nThe sbt launcher is provided by [Paul Phillips][sbt-extras].\n\n\n## Stuff todo\n\n- documentation\n- some more tests\n- contrib modules, that included\n    - support for scalaz type classes\n    - support for functionaljava classes\n    - support for guava classes\n\n## License\n\nCopyright 2014 Paul Horn\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n    http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n\n[ci-img]: https://img.shields.io/travis/knutwalker/transducers-scala/master.svg\n[coverage-img]: https://img.shields.io/codecov/c/github/knutwalker/transducers-scala/master.svg\n[maven-img]: https://img.shields.io/maven-central/v/de.knutwalker/transducers-scala_2.11.svg?label=latest\n[license-img]: https://img.shields.io/badge/license-APACHE_2-green.svg\n\n[ci]: https://travis-ci.org/knutwalker/transducers-scala\n[coverage]: https://codecov.io/github/knutwalker/transducers-scala\n[maven]: http://search.maven.org/#search|ga|1|g%3A%22de.knutwalker%22%20AND%20a%3Atransducers-scala*_2.11\n[license]: https://www.apache.org/licenses/LICENSE-2.0\n\n[install]: http://knutwalker.github.io/transducers-scala/install.html\n[usage]: http://knutwalker.github.io/transducers-scala/guide.html\n[psp-std]: https://github.com/paulp/psp-std/\n[transducers-java]: https://github.com/cognitect-labs/transducers-java\n[transducers-yt]: https://www.youtube.com/watch?v=6mTbuzafcII\n[transducers-blog]: http://blog.cognitect.com/blog/2014/8/6/transducers-are-coming\n[sbt-extras]: https://github.com/paulp/sbt-extras\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fknutwalker%2Ftransducers-scala","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fknutwalker%2Ftransducers-scala","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fknutwalker%2Ftransducers-scala/lists"}