{"id":19502343,"url":"https://github.com/zio/zio-direct","last_synced_at":"2025-07-15T21:46:34.432Z","repository":{"id":64084060,"uuid":"556795715","full_name":"zio/zio-direct","owner":"zio","description":"Direct-Style Programming for ZIO","archived":false,"fork":false,"pushed_at":"2023-06-02T07:44:28.000Z","size":6431,"stargazers_count":149,"open_issues_count":13,"forks_count":13,"subscribers_count":11,"default_branch":"main","last_synced_at":"2024-04-23T05:29:28.352Z","etag":null,"topics":["async-await","effect-system","functional-programming","meta-programming","scala"],"latest_commit_sha":null,"homepage":"https://zio.dev/zio-direct","language":"Scala","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/zio.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}},"created_at":"2022-10-24T14:27:00.000Z","updated_at":"2024-04-19T05:33:14.000Z","dependencies_parsed_at":"2023-02-17T11:15:35.822Z","dependency_job_id":null,"html_url":"https://github.com/zio/zio-direct","commit_stats":null,"previous_names":[],"tags_count":6,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zio%2Fzio-direct","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zio%2Fzio-direct/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zio%2Fzio-direct/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zio%2Fzio-direct/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/zio","download_url":"https://codeload.github.com/zio/zio-direct/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":224019338,"owners_count":17242178,"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":["async-await","effect-system","functional-programming","meta-programming","scala"],"created_at":"2024-11-10T22:16:08.785Z","updated_at":"2024-11-10T22:16:09.994Z","avatar_url":"https://github.com/zio.png","language":"Scala","funding_links":[],"categories":[],"sub_categories":[],"readme":"[//]: # (This file was autogenerated using `zio-sbt-website` plugin via `sbt generateReadme` command.)\n[//]: # (So please do not edit it manually. Instead, change \"docs/index.md\" file or sbt setting keys)\n[//]: # (e.g. \"readmeDocumentation\" and \"readmeSupport\".)\n\n# ZIO Direct Style\n\nZIO Direct Style is a library that allows using directly-style i.e. imperative programming with ZIO effects which is based on the Monadless paradigm.\n\n[![Development](https://img.shields.io/badge/Project%20Stage-Development-green.svg)](https://github.com/zio/zio/wiki/Project-Stages) ![CI Badge](https://github.com/zio/zio-direct/workflows/CI/badge.svg) [![Sonatype Releases](https://img.shields.io/nexus/r/https/oss.sonatype.org/dev.zio/zio-direct_3.svg?label=Sonatype%20Release)](https://oss.sonatype.org/content/repositories/releases/dev/zio/zio-direct_3/) [![Sonatype Snapshots](https://img.shields.io/nexus/s/https/oss.sonatype.org/dev.zio/zio-direct_3.svg?label=Sonatype%20Snapshot)](https://oss.sonatype.org/content/repositories/snapshots/dev/zio/zio-direct_3/) [![javadoc](https://javadoc.io/badge2/dev.zio/zio-direct-docs_3/javadoc.svg)](https://javadoc.io/doc/dev.zio/zio-direct-docs_3) [![ZIO Direct Style](https://img.shields.io/github/stars/zio/zio-direct?style=social)](https://github.com/zio/zio-direct)\n\n## Installation\n\nTo use zio-direct, add the following to your `build.sbt` file.\n\n```scala\nlibraryDependencies += \"dev.zio\" %% \"zio-direct\" % \"1.0.0-RC7\"\n```\n\nYou can also use zio-direct with ZStream and ZPure by importing the following modules.\n\u003e Currently this is only supported in Scala 3.\n\n```scala\n// ZStream\nlibraryDependencies += \"dev.zio\" %% \"zio-direct-streams\" % \"1.0.0-RC7\"\n// ZPure\nlibraryDependencies += \"dev.zio\" %% \"zio-direct-pure\" % \"1.0.0-RC7\"\n```\nSee the [Other Supported Monads](docs/other-supported-monads.md) section for more details.\n\n## IDE Support\n\nThe preferred IDE to use with ZIO-Direct is Visual Studio Code + Metals. This is because Metals correctly reads the returns from `defer` calls directly from the Scala compiler which is not the case of IntelliJ. To remedy this issue, a Library Extension is provided for ZIO-Direct. See the [IntelliJ Support](docs/intellij-support.md) section for more details.\n\n## Introduction\n\nTalk at Functional Scala 2022:\n* Video - https://www.youtube.com/watch?v=DgqfLfzq5eo\n* Slides - https://www.slideshare.net/deusaquilus/ziodirect-functional-scala-2022\n\nZIO-Direct allows direct style programming with ZIO. This library provides a *syntactic sugar* that is more powerful than for-comprehensions as well as more natural to use. Simply add the `.run` suffix to any ZIO effect in order to retrieve its value.\n\nZIO-Direct works by using macros to rewrite sequential code into flatMap-chains based on the [Monadless](https://github.com/monadless/monadless) paradigm. The values resulting in `.run` calls from the ZIO effects are not actually awaited. Instead, they are rolled-up into a chain of flatMaps.\n\nFor example, in imperative programming operations typically are done in a simple set of steps.\n```scala\nobject FileOps:\n  def read(file: File): String\n  def write(file: File, content: String): Unit\n\nval textA = read(fileA)\nval textB = read(fileB)\nwrite(fileC, textA + textB)\n```\n\nUsing functional programming, the equivalent of this functionality is a set of nested flatMap-chains.\n```scala\nobject FileOps\n  def read(file: File): ZIO[Any, Throwable, String]\n  def write(file: File, content: String): ZIO[Any, Throwable, Unit]\n\nread(fileA).flatMap { textA =\u003e\n  read(fileB).flatMap { textB =\u003e\n    write(fileC, textA + textB)\n  }\n}\n```\n\nIn order to avoid this complexity scala provides a for-comprehension syntactic sugar.\n```scala\nfor {\n  textA \u003c- read(fileA)\n  textB \u003c- read(fileB)\n  _ \u003c- write(fileC, textA + textB)\n} yield ()\n```\n\nUnfortunately this syntactic sugar is limited in many cases, for example, inserting a conditional value inside is impossible.\n```scala\nfor {\n  textA \u003c- read(fileA)\n  // Not a possible syntax\n  if (fileA.contains(\"some string\")) {\n    textB \u003c- read(fileB)\n    _ \u003c- write(fileC, textA + textB)\n  }\n} yield ()\n```\n\nZIO-Direct offers an equivalent syntactic sugar that is more ergonomic and allows many constructs that for-comprehensions do not.\n```scala\ndefer {\n  val textA = read(fileA).run\n  if (fileA.contains(\"some string\")) {\n    val textB = read(fileB).run\n    write(fileC, textA + textB).run\n  }\n}\n```\n\n\n# ZIO-Tailored\nZIO-Direct is specifically tailored to ZIO capabilities as it supports Environment and Error composition in ZIO effects similar to the for-comprehension.\n\n```scala\nval out: ZIO[CustomerConfig \u0026 DistributorConfig, CustomerGetException | DistrubutorGetException, (Customer, Distributor)] =\n  defer {\n    // Get a customer-configuration object from the environment and extract its .url field\n    val custUrl: String = ZIO.service[CustomerConfig].run.url\n    // Get a distributor-configuration from the environment and extract its .url field\n    val distUrl: String = ZIO.service[DistributorConfig].run.url\n    (\n      // Use the two configurations to make an HTTP-call\n      parseCustomer(httpGetCustomer(custUrl).run),\n      parseDistrubutor(httpGetDistributor(distUrl).run)\n    )\n  }\n```\n\n## Branching and Looping Support\nUnlike the for-comprehension, ZIO-Direct supports branching and looping in the use of flatMaps composition.\nLet's have a look at a another non-trivial example.\n\n```scala\nclass Database:\n  def nextRow(): ZIO[Any, Throwable, Row]\n  def hasNextRow(): ZIO[Any, Throwable, Boolean]\n  def lockNextRow(): ZIO[Any, Throwable, Boolean]\nobject Database:\n  def open: ZIO[Any, Throwable, Database]\n\ndefer {\n  // Open a database connection\n  val db = Database.open().run\n  // See if there is is a next-row\n  while (db.hasNextRow().run) {\n    // try to lock, if aquired continue\n    if (db.lockNextRow().run)\n      val nextRow = db.nextRow().run\n      doSomethingWith(nextRow)\n    else\n      waitT()\n  }\n}\n```\n\u003e NOTE: The above database-api is imaginary.\n\nThe above code needs to be translated into something like this:\n\n```scala\nDatabase.open.flatMap { db =\u003e\n  def whileFun(): ZIO[Any, Throwable, Unit] =\n    db.hasNextRow().flatMap { hasNextRow =\u003e\n      if (hasNextRow)(\n        db.lockNextRow().flatMap { lockNextRow =\u003e\n          if (!lockNextRow)\n            db.nextRow().map(nextRow =\u003e doSomethingWith(nextRow))\n          else\n            ZIO.succeed(waitT())\n        }\n      ).flatMap(_ =\u003e whileFun())\n      else\n        ZIO.unit\n    }\n  whileFun()\n}\n```\n\nNote that normally this is the exact code that would have to be written to capture such functionality For-comprehensions do not provide a way to do looping and branching so in such cases\na combination of flatMaps and recursion is necessary to avoid calling effects unnecessarily.\n\n## Great for Refs and FiberRefs!\n\nZIO-direct makes it much easier to use ZIO mutable Ref and FiberRef variables. Since retrieveing and updating Ref and FiberRef variables requries a flatMap/for-comprehension call, it is typically very difficult to use them with branching/looping constructs. ZIO-direct makes these cases much easier.\n\n```scala\nclass DatabaseApi {\n  val connRef = FiberRef.make[Option[Connection]](None)\n  def openConnection(): Connection = lowLevelDatabaseApi.openConnection()\n  def transaction(action: Action) =\n    defer {\n      val conn = connRef.get.run\n      if (conn == None) {\n        connRef.set(Some(openConnection())).run\n      }\n      val conn1 = connRef.get.run\n      conn.execute(action).run\n    }\n}\n```\n\nInstead of having to write the following code:\n```scala\nclass DatabaseApi {\n  val connRef = FiberRef.make[Option[Connection]](None)\n  def openConnection(): Connection = lowLevelDatabaseApi.openConnection()\n  def transaction(action: Action) =\n    connRef.get.flatMap { conn =\u003e\n      (if (conn == None) {\n        connRef.set(Some(openConnection()))\n      } else {\n        ZIO.unit\n      }).flatMap(_ =\u003e connRef.get.flatMap { conn1 =\u003e\n        conn1.execute(action)\n      })\n    }\n\n  // Note that for-comprehensions do not help very much in this use-case\n  def transaction0(action: Action) =\n    for {\n      conn \u003c- connRef.get\n      _ \u003c- if (conn == None) {\n        connRef.set(Some(openConnection()))\n      } else {\n        ZIO.unit\n      }\n      conn1 \u003c- connRef.get\n      _ \u003c- conn1.execute(action)\n    }\n}\n```\n\n## Documentation\n\nLearn more on the [ZIO Direct Style homepage](https://zio.dev/zio-direct)!\n\n## Contributing\n\nFor the general guidelines, see ZIO [contributor's guide](https://zio.dev/about/contributing).\n\n## Code of Conduct\n\nSee the [Code of Conduct](https://zio.dev/about/code-of-conduct)\n\n## Support\n\nCome chat with us on [![Badge-Discord]][Link-Discord].\n\n[Badge-Discord]: https://img.shields.io/discord/629491597070827530?logo=discord \"chat on discord\"\n[Link-Discord]: https://discord.gg/2ccFBr4 \"Discord\"\n\n## License\n\n[License](LICENSE)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzio%2Fzio-direct","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fzio%2Fzio-direct","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzio%2Fzio-direct/lists"}