-
Notifications
You must be signed in to change notification settings - Fork 451
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
Allow to recover to Option<A> in Option.catch #2437
Conversation
bf876f8
to
9ede56f
Compare
@@ -339,12 +339,11 @@ sealed class Option<out A> { | |||
|
|||
@JvmStatic | |||
@JvmName("tryCatch") | |||
inline fun <A> catch(recover: (Throwable) -> Unit, f: () -> A): Option<A> = | |||
inline fun <A> catch(recover: (Throwable) -> Option<A>, f: () -> A): Option<A> = |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
inline fun <A> catch(recover: (Throwable) -> Option<A>, f: () -> A): Option<A> = | |
@JvmOverloads | |
inline fun <A> catch(recover: (Throwable) -> Option<A> = { None }, f: () -> A): Option<A> = |
This channge would not cause any binary breaking change due to the default argument and @JvmOverloads
creating a second method with the original signature.
I'm wondering if we should keep the original function, or if we should be more strict like in this PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should keep the original function as well. It's useful in suspend
code?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi, @nomisRev, there could be 2 ways of handling exceptions for Option
. The library user would decide which version to use. But the names for JVM have to be different. I got this error when I had 2 versions of the catch
function
git/arrow/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/Option.kt: (331, 14): Platform declaration clash: The following declarations have the same JVM signature (tryCatch(Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function0;)Larrow/core/Option;):
fun <A> tryCatch(recover: (Throwable) -> Option<A#1 (type parameter of arrow.core.Option.tryCatch)>, f: () -> A#1): Option<A#2 (type parameter of arrow.core.Option.Companion.catch)> defined in arrow.core.Option
fun <A> tryCatch(recover: (Throwable) -> Unit, f: () -> A#3 (type parameter of arrow.core.Option.tryCatch)): Option<A#4 (type parameter of arrow.core.Option.Companion.catch)> defined in arrow.core.Option
I have no good name for my variant :-(.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hey @dnowak,
Damn, that's too bad that it conflicts :(
What about the following?
It deprecates the current function and replaces it with the one you proposed. Alternatively, it also adds the = { None }
variant but as an explicit overload rather than as an automatically generated one.
That way we can use tryCatchOrNone
as the JVM name instead.
@JvmStatic
@JvmName("tryCatch")
@Deprecated(
"Side-effecting recover which loses Throwable is no longer supported",
ReplaceWith("Option.catch({ recover(it); None }, f)")
)
inline fun <A> catch(recover: (Throwable) -> Unit, f: () -> A): Option<A> =
try {
Some(f())
} catch (t: Throwable) {
recover(t.nonFatalOrThrow())
None
}
@JvmStatic
@JvmName("tryCatchOrNone")
inline fun <A> catch(f: () -> A): Option<A> =
try {
Some(f())
} catch (t: Throwable) {
t.nonFatalOrThrow()
None
}
@JvmStatic
@JvmName("tryCatch")
inline fun <A> catch(recover: (Throwable) -> Option<A>, f: () -> A): Option<A> =
try {
Some(f())
} catch (t: Throwable) {
recover(t.nonFatalOrThrow())
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi @nomisRev ,
The deprecated variant also needs a specific name for Java. I propose catchOrSideEffect
. It will change Java API. I do not know how important is the stability of Java API. Anyway here is my current proposal:
@JvmStatic
@JvmName("tryCatchOrSideEffect")
@Deprecated(
"Side-effecting recover which loses Throwable is no longer supported",
ReplaceWith("Option.catch({ recover(it); None }, f)")
)
inline fun <A> catch(recover: (Throwable) -> Unit, f: () -> A): Option<A> =
try {
Some(f())
} catch (t: Throwable) {
recover(t.nonFatalOrThrow())
None
}
@JvmStatic
@JvmName("tryCatchOrNone")
/**
* Ignores exceptions and returns None if one is thrown
*/
inline fun <A> catch(f: () -> A): Option<A> {
val recover: (Throwable) -> Option<A> = { None }
return catch(recover, f)
}
@JvmStatic
@JvmName("tryCatch")
inline fun <A> catch(recover: (Throwable) -> Option<A>, f: () -> A): Option<A> =
try {
Some(f())
} catch (t: Throwable) {
recover(t.nonFatalOrThrow())
}
PS. How to add such a nice block of code into a comment? :-)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry, for the late response @dnowak. Thanks, @AzimMuradov.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for making this PR and contribution! 🙌 This was definitely missing!!
469450b
to
8137936
Compare
8137936
to
522b485
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for the contributions @dnowak! 🙌 🙌
This will be included in the 1.0.0-M1 release soon ;)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thanks @dnowak !
@@ -339,12 +339,11 @@ sealed class Option<out A> { | |||
|
|||
@JvmStatic | |||
@JvmName("tryCatch") | |||
inline fun <A> catch(recover: (Throwable) -> Unit, f: () -> A): Option<A> = | |||
inline fun <A> catch(recover: (Throwable) -> Option<A>, f: () -> A): Option<A> = |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should keep the original function as well. It's useful in suspend
code?
The current version of
catch
that has(Throwable) -> Unit
as recover action does not allow to handle the exception in any usable way. The only possible action is a side effect (ie. to log the exception).I think that we should have the possibility to recover from
Throwable
toOpton<A>
-> recover type should be(Throwable) -> Option<A>
. This is much more useful than executing some side effect.I have changed the current function. Maybe it should be deprecated and a new one added?