GithubHelp home page GithubHelp logo

zio / zio-direct Goto Github PK

View Code? Open in Web Editor NEW
150.0 11.0 13.0 6.28 MB

Direct-Style Programming for ZIO

Home Page: https://zio.dev/zio-direct

Scala 99.93% Shell 0.07%
async-await effect-system functional-programming meta-programming scala

zio-direct's People

Contributors

deusaquilus avatar dzikoysk avatar github-actions[bot] avatar khajavi avatar swoogles avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

zio-direct's Issues

Surprising behavior when converting ZIO[_, _, Nothing]

I was converting some code:

val oldStyle =
  for 
    _ <- printLine("Hi")
    _ <- ZIO.fail("Error!")
  yield ()

into

val directStyle =
  defer {
    printLine("Hi").run
    ZIO.fail("Error!").run
  }

and got this error message:

missing arguments for method apply in trait deferCall
  defer {

Is there a fundamental reason why we cannot return ZIOs with a Nothing result inside defer blocks?
If so, is there a way we could provide better error messages in this situation?
There are some great custom compilation error messages in this library, so I was surprised when I hit this one.
It took me a while to figure out what was actually causing the problem.

Guards in `for` loops do not compile

for loops in Scala 3 (and 2.x) support guards, however the following does not compile:

def getNums(): UIO[List[Int]] = ZIO.succeed(List(1, 2, 3))
def printNum(n: Int): UIO[Unit] = ZIO.succeed(println(n))
defer {
  for {
    n <- getNums().run
    if n % 2 == 0
  } printNum(n).run // Error: While expanding a macro, a reference to parameter n
}                   // was used outside the scope where it was defined

It seems it has something to do with how guards are desugared, the following also doesn't compile:

defer { 
  getNums().run.withFilter(n => n % 2 == 0).foreach(n => printNum(n).run)
}

whereas replacing withFilter with filter successfully compiles.

Potential non-sensical Scala 2 macro expansion errors

In the issue #16 it was discovered that sometimes the presence of a 2nd overloaded method with an extra argument can sometimes "trick" Scala 2 into thinking a correct macro-method is correct.

It was discovered that when you add a 2nd "dummy method" for example:

  def defer[T](value: T): ZIO[_, _, _] = macro core.Macro.deferImpl[T]
  def defer[T](regex: Something)(value: T): ZIO[_, _, _] = ??? // dummy  method

The Something class can be anything. I tried java.util.Regex which has nothing to do with anything. Note that the 2nd value can also be of type regex and that the 2nd thing does not even need to be a macro.
In order to do this:

        val out =
          defer {
            val i = Ref.make(0).run
            while (i.get.run < 3)
              i.getAndUpdate(i => i + 1).run
            i.get.run
          }

The following above code that normally throws a "macro has not been expanded" error will somehow work.
This is shown in the following branch.
https://github.com/zio/zio-direct/tree/crazy-macro-expansion-error

There are other scenarios where "macro has not been expanded" will occur. for example, if you have a macro the wrong number of arguments:

        val out =
          defer({
            val i = Ref.make(0).run
            while (i.get.run < 3)
              i.getAndUpdate(i => i + 1).run
            i.get.run
          }, null) // add extra 'null' argument

Need to watch out for potential similar issues and think about mitigations.

Support error type elimination within try-catch clauses

To improve the ergonomics of error handling, it would be nice if we could eliminate some union types from the error channel when explicitly handled in a catch block. Maybe we can simulate the symantics of ZIO.catchSome and ZIO.die:

import zio.*
import zio.direct.*

case class ID()
case class Person()
case class ParseError()
case class DBError()

def parseId(s: String): IO[ParseError, ID] = ???
def getPerson(id: ID): IO[DBError, Person] = ???

val t: IO[DBError, Person] = defer {
  try {
    val id = parseId("1").run
    getPerson(id).run
  } // ZIO[Any, DBError | ParseError, Person]
  catch { 
    case v: ParseError => Person()  // eliminate ParseError we return a subtype of Person (simulates ZIO.catchSome)
    case v: ParseError => ZIO.die(???)  // alternatively, terminate the fiber with a defect
  }
}

Mutable collection usage

The following code triggers a 'Detected the use of a mutable collection inside a defer clause.', but I don't think it should lead to any issues.

defer {
    val text = ZIO.succeed("1,2,3").run
    val values = text.split(",").toList
    ZIO.foreach(values)(v => zio.Console.printLine(v))
  }

docs: clarify the issues of monadic DSL

Hi, I see the readme says that the below code doesn't work

for {
  textA <- read(fileA)
  // Not a possible syntax
  if (fileA.contains("some string")) {
    textB <- read(fileB)
    _ <- write(fileC, textA + textB)
  }
} yield ()

However it seems that the code below works:

val o1 = Option(1)
val o2 = Option(1)

// condition in monadic DSL
for {
  a <- o1
  _ <- if true then o1 else o2
} yield ()

// while loop in monadic DSL
for {
  a <- o1
  _ <- Option(while (true) {})
} yield ()

so it seems that control structure is actually supported in the monadic DSL?

Drop reliance on quill-util and make another upstream library to encapsulate ScalaFMT needs

Want to be able to optionally use scalafmt to format code if it is on the path. This is indispensable for .info calls etc... but want to make this optional. Also, don't want to directly compile anything that has to do with scalafmt directly because it has a nasty tendency to spew hundreds of irrelevant protobuff errors. The ideal way to do this would be to create an upstream library that does what Quill's ScalafmtFormat class does. Essentially have a generic FmtUtils library in the ZIO namespace that does basically what quill-util does.

I added a branch to how how Scalafmt could be pulled in directly (https://github.com/zio/zio-direct/tree/pull-in-scalafmt-directly) and it successfully copiles but if anything is wrong with the compile dozens of protobuff errors will spew to the console. Therefore I do not want to use that branch.

Wring typing on `unsafe` block

        val out =
          defer {
            val bar = ZIO.succeed("foo").run
            unsafe {
              "bar"
            }
          }

Expected out to be of type ZIO[Any, Throwable, String] but is ZIO[Any, Throwable, Any].

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.