{"id":13462679,"url":"https://github.com/pointfreeco/swift-gen","last_synced_at":"2025-05-16T09:04:05.644Z","repository":{"id":34361386,"uuid":"164180976","full_name":"pointfreeco/swift-gen","owner":"pointfreeco","description":"🎱 Composable, transformable, controllable randomness.","archived":false,"fork":false,"pushed_at":"2025-03-26T06:00:14.000Z","size":100,"stargazers_count":287,"open_issues_count":4,"forks_count":18,"subscribers_count":5,"default_branch":"main","last_synced_at":"2025-05-15T18:53:54.165Z","etag":null,"topics":["composition","functional-programming","randomness","testing","transformation"],"latest_commit_sha":null,"homepage":"https://www.pointfree.co/episodes/ep49-generative-art-part-1","language":"Swift","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/pointfreeco.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":".github/CODE_OF_CONDUCT.md","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,"zenodo":null}},"created_at":"2019-01-05T04:15:34.000Z","updated_at":"2025-05-14T09:02:53.000Z","dependencies_parsed_at":"2025-04-12T22:27:54.682Z","dependency_job_id":null,"html_url":"https://github.com/pointfreeco/swift-gen","commit_stats":{"total_commits":23,"total_committers":7,"mean_commits":"3.2857142857142856","dds":0.4347826086956522,"last_synced_commit":"b86cc03db04868d52a0c2da81797d81201eefd77"},"previous_names":[],"tags_count":5,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pointfreeco%2Fswift-gen","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pointfreeco%2Fswift-gen/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pointfreeco%2Fswift-gen/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pointfreeco%2Fswift-gen/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/pointfreeco","download_url":"https://codeload.github.com/pointfreeco/swift-gen/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254404330,"owners_count":22065639,"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":["composition","functional-programming","randomness","testing","transformation"],"created_at":"2024-07-31T13:00:18.773Z","updated_at":"2025-05-16T09:04:05.615Z","avatar_url":"https://github.com/pointfreeco.png","language":"Swift","funding_links":[],"categories":["generate resources"],"sub_categories":[],"readme":"# 🎱 Gen\n\n[![CI](https://github.com/pointfreeco/swift-gen/actions/workflows/ci.yml/badge.svg)](https://github.com/pointfreeco/swift-gen/actions/workflows/ci.yml)\n[![](https://img.shields.io/endpoint?url=https%3A%2F%2Fswiftpackageindex.com%2Fapi%2Fpackages%2Fpointfreeco%2Fswift-gen%2Fbadge%3Ftype%3Dswift-versions)](https://swiftpackageindex.com/pointfreeco/swift-gen)\n[![](https://img.shields.io/endpoint?url=https%3A%2F%2Fswiftpackageindex.com%2Fapi%2Fpackages%2Fpointfreeco%2Fswift-gen%2Fbadge%3Ftype%3Dplatforms)](https://swiftpackageindex.com/pointfreeco/swift-gen)\n\nComposable, transformable, controllable randomness.\n\n## Table of Contents\n\n- [Motivation](#motivation)\n- [Examples](#examples)\n- [Installation](#installation)\n- [Interested in learning more?](#interested-in-learning-more)\n- [License](#license)\n\n## Motivation\n\nSwift's randomness API is powerful and simple to use. It allows us to create random values from many basic types, such as booleans and numeric types, and it allows us to randomly shuffle arrays and pluck random elements from collections.\n\nHowever, it does not make it easy for us to extend the randomness API, nor does it provide an API that is composable, which would allow us to create complex types of randomness from simpler pieces.\n\n\nGen is a lightweight wrapper over Swift's randomness APIs that makes it easy to build custom generators of any kind of value.\n\n## Examples\n\nGen's namesake type, `Gen`, is responsible for producing random values. Most often you will reach for one of the static variables inside `Gen` to get access to a `Gen` value:\n\n``` swift\nGen.bool\n// Gen\u003cBool\u003e\n```\n\nRather than immediately producing a random value, `Gen` describes a random value that can be produced by calling its `run` method:\n\n``` swift\nlet myGen = Gen.bool\n// Gen\u003cBool\u003e\n\nmyGen.run() // true\nmyGen.run() // true\nmyGen.run() // false\n```\n\nEvery random function that comes with Swift is also available as a static function on `Gen`:\n\n|  Swift's API | Gen's API |\n| --- | --- |\n| `Int.random(in: 0...9)` | `Gen.int(in: 0...9)` |                       \n| `Double.random(in: 0...9)` | `Gen.double(in: 0...9)` |                       \n| `Bool.random()` | `Gen.bool` |                       \n| `[1, 2, 3].randomElement()` | `Gen.element(of: [1, 2, 3])` |                       \n| `[1, 2, 3].shuffled()` | `Gen.shuffle([1, 2, 3])` |                       \n\nThe reason it is powerful to wrap randomness in the `Gen` type is that we can make the `Gen` type composable. For example, a generator of integers can be turned into a generator of numeric strings with a simple application of the `map` function:\n\n``` swift\nlet digit = Gen.int(in: 0...9)           // Gen\u003cInt\u003e\nlet stringDigit = digit.map(String.init) // Gen\u003cString\u003e\n\nstringDigit.run() // \"7\"\nstringDigit.run() // \"1\"\nstringDigit.run() // \"3\"\n```\n\nAlready this is a form of randomness that Swift's API's do not provide out of the box.\n\nGen provides many operators for generating new types of randomness, such as `map`, `flatMap` and `zip`, as well as helper functions for generating random arrays, sets, dictionaries, strings, distributions and more! A random password generator, for example, is just a few operators away.\n\n``` swift\n// Take a generator of random letters and numbers.\nlet password = Gen.letterOrNumber\n  // Generate 6-character strings of them.\n  .string(of: .always(6))\n  // Generate 3 segments of these strings.\n  .array(of: .always(3))\n  // And join them.\n  .map { $0.joined(separator: \"-\") }\n\npassword.run() // \"9BiGYA-fmvsOf-VYDtDv\"\npassword.run() // \"dS2MGr-FQSuC4-ZLEicl\"\npassword.run() // \"YusZGF-HILrCo-rNGfCA\"\n```\n\nThis kind of composition makes it simple to generate random values of anything.\n\n``` swift\n// Use `zip` to combine generators together and build structures.\n\nlet randomPoint = zip(.int(in: -10...10), .int(in: -10...10))\n  .map(CGPoint.init(x:y:))\n// Gen\u003cCGPoint\u003e\n```\n\nBut composability isn't the only reason the `Gen` type shines. By delaying the creation of random values until the `run` method is invoked, we allow ourselves to control randomness in circumstances where we need determinism, such as tests. The `run` method has an overload that takes a `RandomNumberGenerator` value, which is Swift's protocol that powers their randomness API. By default it uses the `SystemRandomNumberGenerator`, which is a good source of randomness, but we can also provide a seedable \"pseudo\" random number generator, so that we can get predictable results in tests:\n\n``` swift\nvar xoshiro = Xoshiro(seed: 0)\nGen.int(in: 0...9).run(using: \u0026xoshiro) // \"1\"\nGen.int(in: 0...9).run(using: \u0026xoshiro) // \"0\"\nGen.int(in: 0...9).run(using: \u0026xoshiro) // \"4\"\n\nxoshiro = Xoshiro(seed: 0)\nGen.int(in: 0...9).run(using: \u0026xoshiro) // \"1\"\nGen.int(in: 0...9).run(using: \u0026xoshiro) // \"0\"\nGen.int(in: 0...9).run(using: \u0026xoshiro) // \"4\"\n```\n\nThis means you don't have to sacrifice testability when leveraging randomness in your application.\n\nFor more examples of using Gen to build complex randomness, see our [blog post](https://www.pointfree.co/blog/posts/19-random-zalgo-generator) on creating a Zalgo generator and our two-part video series ([part 1](https://www.pointfree.co/episodes/ep49-generative-art-part-1) and [part 2](https://www.pointfree.co/episodes/ep50-generative-art-part-2)) on creating generative art.\n\n## Installation\n\nIf you want to use Gen in a project that uses [SwiftPM](https://swift.org/package-manager/), it's as simple as adding a `dependencies` clause to your `Package.swift`:\n\n``` swift\ndependencies: [\n  .package(url: \"https://github.com/pointfreeco/swift-gen.git\", from: \"0.4.0\")\n]\n```\n\n## Interested in learning more?\n\nThese concepts (and more) are explored thoroughly in [Point-Free](https://www.pointfree.co), a video series exploring functional programming and Swift hosted by [Brandon Williams](https://github.com/mbrandonw) and [Stephen Celis](https://github.com/stephencelis).\n\nThe design of this library was explored in the following [Point-Free](https://www.pointfree.co) episodes:\n\n- [Episode 30](https://www.pointfree.co/episodes/ep30-composable-randomness): Composable Randomness\n- [Episode 31](https://www.pointfree.co/episodes/ep31-decodable-randomness-part-1): Decodable Randomness: Part 1\n- [Episode 32](https://www.pointfree.co/episodes/ep32-decodable-randomness-part-2): Decodable Randomness: Part 2\n- [Episode 47](https://www.pointfree.co/episodes/ep47-predictable-randomness-part-1): Predictable Randomness: Part 1\n- [Episode 48](https://www.pointfree.co/episodes/ep48-predictable-randomness-part-2): Predictable Randomness: Part 2\n- [Episode 49](https://www.pointfree.co/episodes/ep49-generative-art-part-1): Generative Art: Part 1 🆓\n- [Episode 50](https://www.pointfree.co/episodes/ep50-generative-art-part-2): Generative Art: Part 2 🆓\n\n\u003ca href=\"https://www.pointfree.co/episodes/ep30-composable-randomness\"\u003e\n  \u003cimg alt=\"video poster image\" src=\"https://d3rccdn33rt8ze.cloudfront.net/episodes/0030.jpeg\" width=\"600\"\u003e\n\u003c/a\u003e\n\n## License\n\nAll modules are released under the MIT license. See [LICENSE](LICENSE) for details.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpointfreeco%2Fswift-gen","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpointfreeco%2Fswift-gen","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpointfreeco%2Fswift-gen/lists"}