Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Conversation

@adamgfraser
Copy link
Contributor

@adamgfraser adamgfraser commented Aug 2, 2020

Currently combinators for effectually transforming collections generally take an Iterable[A] and return a List[B], resulting in loss of information and requiring separate versions of combinators to preserve the specific collection type. This results in code duplication (e.g. Chunk#mapM versus ZIO.foreach) and lack of support for some collection types (e.g. there is not currently a combinator to effectually transform a Vector and preserve its specific collection type).

This PR uses the BuildFrom machinery in the Scala standard library to support transformation methods that return the same collection type ZIO, ZManaged, and ZSTM. Variants of foreach that are specialized to Chunk are removed since Chunk is a subtype of Iterable and Chunk#mapM and variants are reimplemented in terms of ZIO.foreach.

Resolves #2781. Resolves #3369. Resolves #3942. Resolves #4032.

@adamgfraser adamgfraser requested review from iravid and jdegoes August 2, 2020 08:26
iravid
iravid previously approved these changes Aug 2, 2020
Copy link
Member

@iravid iravid left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks fantastic.

Copy link
Member

@ghostdogpr ghostdogpr left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wow, this is nice!

/**
* Applies the functionw `f` to each element of the `Iterable[A]` in parallel,
* and returns the results in a new `List[B]`.
* Applies the functionw `f` to each element of the `Collection[A]` in parallel,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not from your PR but I just noticed a small typo here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! Fixed now!

},
testM("empty input") {
assertM(ZIO.forkAll(List.empty).flatMap(_.join))(equalTo(List.empty))
assertM(ZIO.forkAll(List.empty[ZIO[Any, Nothing, Unit]]).flatMap(_.join))(equalTo(List.empty))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the price we pay, eh?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It works fine on Scala 2.12. We don't have to pay it if scala/bug#12104 is resolved.

tArray <- makeStair(N).commit
findFiber <- tArray.findLast(_ % largePrime == 0).commit.fork
_ <- STM.foreach(0 until N)(i => tArray.update(i, _ => 1)).commit
_ <- STM.foreach(List.range(0, N))(i => tArray.update(i, _ => 1)).commit
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The old 0 until N no longer works?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ranges work if it is an inclusive range but not an exclusive range. The same issue applies to Future.traverse. This seems like a bug. Opened an issue for it at scala/bug#12105.

}
dest.map(_.result())
}
ZIO.foreach(self)(f)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

😍

def poll: UIO[Option[Exit[E, Collection[A]]]] =
UIO
.foreach(fibers)(_.poll)
.foreach[Fiber[E, A], Option[Exit[E, A]], Iterable](fibers)(_.poll)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yikes! These are some pretty monstrous type annotations. Could partial application trick help here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This can be rewritten as UIO.foreach(fibers: Iterable[Fiber[E, A]])(_.poll).

ZManaged(ZIO.foreach(as)(f(_).zio).map { result =>
val (fins, _) = result.unzip
(e => ZIO.foreach(fins.reverse)(_.apply(e)), ())
(e => ZIO.foreach(fins.toList.reverse)(_.apply(e)), ())
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems like we can no longer work with Iterable. Could a low priority implicit build from compat work to restore that?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this actually isn't an issue with our implementation at all. reverse isn't defined on Iterable so since we no longer automatically return a List we don't have a Seq that can be reverse.

supervisedFibers.flatMap { fibers =>
ZIO
.foreach(fibers)(_.status.filterOrFail {
.foreach[Any, Unit, Fiber.Runtime[Any, Any], Fiber.Status, Iterable](fibers)(_.status.filterOrFail {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

😱 If there's a way to fix this, we really should explore that.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This one is particular bad because Set is invariant. All we really need here is a way to widen Set to Iterable, which unfortunately the compiler won't do for us automatically here. On Scala 2.12 we can just do foreach(fibers.toIterable)(???) but that doesn't work on Scala 2.13 because now toIterable returns this.type so it doesn't actually widen. Let me see if we can use a type ascription on fibers.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This one is fixed now with the new foreach variant for Set.

Copy link
Member

@jdegoes jdegoes left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Amazing work that makes ZIO more "batteries included", quite weakening the main case for ZIO Prelude. 😆 (Which is a good thing.)

My only reservation right now is on type inference in the foreach signatures, but maybe we can do something about that?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

4 participants