@Avasil Oh, one final bit of trickiness: you can't call getClass
on a thunked value in Scala and expect to get the class of the thunk, which is what you need. For example, to trace delay
or >>
. So you're probably going to need to implement a tiny helper in Java that has the class metadata to trick scalac into passing the thunk
along without evaluation. In other words, what scalac does when it sees the following:
def foo(s: => String) = bar(s)
def bar(s: => String) = ...
bar
gets the raw thunk that was passed to foo
, without re-wrapping. If you can define bar
in Java, then you can take that thunk (which will be of type scala.Function0
) and call getClass
on it without forcing. You don't have that option in Scala, since calling s.getClass
will force the thunk and give you the Class
of its contents.
@SystemFw
is Simon Marlow's note on maskUninterruptable: every use should be viewed with extreme suspicion.
well, we can say: every use of uncancelable that ignores restore should be ....
Fair, though maskUninterruptable
still has restore
as well, and Simon suggests it be viewed with unconditional suspicion.
The "no special cases" thing is very appealing, and in a sense cancelable
would create an unbounded number of special cases. I strongly suspect though that the only people who would use it would be authors of things like Deferred
, and most code would just ignore it. That would certainly be the best practice.
Ref
but I'm not sure how I could make the wait part. Is there is that look like that which exists or is there good exemple that can help me to make this?
F[A]
that would be potentially problematic
Ref
+ Deferred
you actually already made one !
Bracket
instance
Bracket
for any MonadError
type ValidationResult[A] = ValidatedNec[JobPostError, A]
override def createJobPost(
newJobPost: JobPost
): IO[ValidatedNec[String, JobPost]] = {
// TODO: Add logger here on every field validation
val localValidation: ValidationResult[JobPost] = (
validateNoop(newJobPost.id),
validateEmptiness("Job post title".some, newJobPost.title),
validateEmptiness("Job post description".some,
newJobPost.description),
validateNoop(newJobPost.createdAt),
validateNoop(newJobPost.modifiedAt)
).mapN(JobPost)
val databaseValidations: IO[ValidationResult[JobPost]] = (for {
_ <- Logger[ConnectionIO].info("Validating job title")
title <- validateTitleExistence(newJobPost)
_ <- Logger[ConnectionIO].info("Validating job description")
description <- validateNoop(newJobPost.description).pure[ConnectionIO]
createdAt <- validateNoop(newJobPost.createdAt).pure[ConnectionIO]
modifiedAt <- validateNoop(newJobPost.modifiedAt).pure[ConnectionIO]
id <- validateNoop(newJobPost.id).pure[ConnectionIO]
} yield {
(id, title, description, createdAt, modifiedAt).mapN(JobPost)
}).transact(xa)
val response: IO[ValidatedNec[String, JobPost]] =
localValidation match {
case Valid(_) => databaseValidations.map(_.leftMap(_.map(_.errorMessage)))
case Invalid(e) => e.map(_.errorMessage).invalid[JobPost].pure[IO]
}
response
}