-
Notifications
You must be signed in to change notification settings - Fork 30
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Proposal: either.catching should be a boundary operator #150
Comments
Alternative is to have and use two control structures, as stdlib has it right now - |
This is also an option: import scala.util.{Try, Failure, Success}
extension [A](inline t: Try[A])
transparent inline def ok(): A =
summonFrom {
case given boundary.Label[Either[Throwable, Nothing]] =>
t match
case Failure(t) => break(Left(t))
case Success(a) => a
case given boundary.Label[Either[Nothing, Nothing]] =>
error(
"The enclosing `either` call uses a different error type.\nIf it's explicitly typed, is the error type correct? For `Try` error type has to be `Throwable`."
)
case _ => error("`.ok()` can only be used within an `either` call.\nIs it present?")
} import ox.*, either.*
import scala.util.*
import java.io.IOException
case class CaseEx(msg: String) extends Exception(msg)
def niceSafeFunc(): Try[String] = Try("something")
def thisFuncCanThrow(str: String): String = throw CaseEx("lying signature")
def safeFunc: Either[Throwable, Int] = either[Throwable, Int] {
val first = niceSafeFunc().ok()
// do things
val output: String = Try(thisFuncCanThrow(first)).ok()
// do stuff
output.toInt // this can also throw and one can easily forget about it when used to IO monads always catching
}
safeFunc shouldEqual Left(CaseEx("lying signature")) |
Yes, but what happens when you run the In cats-effect, what does an What can we do in Ox? (a) always go with returning |
Haha, before we get into a very deep discussion about error channels, modeling of error channels (only exceptions are built-in, Try or Either require special handling and syntax) and whether exceptions should be used (I'm firmly in the no, they shouldn't team btw), let's get this out of the way: Proposal is to turn catching into a boundary operator too: from this: inline def catching[T](inline t: => T): Either[Throwable, T] =
try Right(t)
catch case NonFatal(e) => Left(e) to this: inline def catching[T](inline t: Label[Either[Throwable, T]] ?=> T): Either[Throwable, T] =
try boundary(Right(t))
catch case NonFatal(e) => Left(e) |
Exceptions are a fact of life on the JVM, I think the best you can do is try to push them to the role of "panics". But back to the main topic: I suppose, but then it would make sense to move it to |
Sure, in Scala code - yeah, treating them as panics is probably mostly fine. Issue is: they are very often used for handling of things that should not be panics. A common example is, of course, |
using .toInt instead of .toIntOption when you're not 100% sure that it's a number is a bug - especially when you're not catching the exception. But sure, let's add the label, and move it to |
Sure it is but that code can be in a dependency lib code. I'll push a PR
tomorrow.
…On Sat 15. Jun 2024 at 13:34, Adam Warski ***@***.***> wrote:
using .toInt instead of .toIntOption when you're not 100% sure that it's a
number is a bug - especially when you're not catching the exception. But
sure, let's add the label, and move it to object either
—
Reply to this email directly, view it on GitHub
<#150 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/ACBVNUW3WM2OJDYRSU7VKLLZHQRC3AVCNFSM6AAAAABI2LRYFOVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDCNRZGM3TOMBSHE>
.
You are receiving this because you authored the thread.Message ID:
***@***.***>
|
implemented with #167 |
One of the least pleasant surprises when working with direct style scala using Ox is that we're back to exception throwing and lying signatures. I found out the hard way that one of the nicest things one gets from monadic effects is that they capture exceptions pervasively so in 99% of cases if a function gets you an
IO[A]
, you will get anIO[A]
and not an exception. This is not true with ox either combinators as either does not naturally capture (and hence why maybe the idea to haveResult[A]
that has aThrowable
error channel is not that bad idea? in a different discussion we could debate ifTry
catching on all combinators is still bad, given thatIO
monads also do that? maybe Ox should have combinators forTry
?). Either way (pun not intended), given thateither {}
block does not catch exceptions but returns anEither[E, A]
there seems to be no nice, useful way to work with both structuredeither
and exceptions in one go. Let me visualize this:this obviously crashes:
because exceptions subvert the type of
safeFunc
. With current state of ox when one is facing such unsafe APIs one can only do:which does the job at the cost of changing the return type of
safeFunc
toEither[Throwable, Int]
but it's also quite redundant - I want to use nice boundary-based combinators, I want to be able to use.ok()
but to do that I have to have a nestedeither
scope. Proposal is to turncatching
into a boundary operator too:from this:
to this:
so that in the end we get:
Your thoughts?
The text was updated successfully, but these errors were encountered: