-
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
[PROPOSAL] Option API deprecation, and preparation for 2.x.x #2913
Conversation
Kover Report
|
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.
Looks good to me so far. I think it was missing some imports in the ReplaceWith
🤔
arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/Option.kt
Outdated
Show resolved
Hide resolved
arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/Option.kt
Outdated
Show resolved
Hide resolved
arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/Option.kt
Outdated
Show resolved
Hide resolved
arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/Option.kt
Outdated
Show resolved
Hide resolved
arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/Option.kt
Outdated
Show resolved
Hide resolved
arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/Option.kt
Outdated
Show resolved
Hide resolved
arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/Option.kt
Outdated
Show resolved
Hide resolved
arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/Option.kt
Outdated
Show resolved
Hide resolved
arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/Option.kt
Outdated
Show resolved
Hide resolved
arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/Option.kt
Outdated
Show resolved
Hide resolved
9a4e423
to
c675811
Compare
Co-authored-by: Simon Vergauwen <nomisRev@users.noreply.github.com>
@nomisRev Do we want to deprecate the |
Yes, we agreed that It's an API that originally came from |
This decision can still be challenged of course. @myuwono would be great to get your review here when it's ready for review. He's one of the biggest users of |
arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/Option.kt
Outdated
Show resolved
Hide resolved
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.
LGTM
arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/Option.kt
Outdated
Show resolved
Hide resolved
@@ -1029,6 +1255,14 @@ public inline fun <A> Option<A>.ensure(error: () -> Unit, predicate: (A) -> Bool | |||
/** | |||
* Returns an Option containing all elements that are instances of specified type parameter [B]. | |||
*/ | |||
@Deprecated( | |||
NicheAPI + "Prefer using option DSL or flatMap", |
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.
This aligns with stdlib for list.filterIsInstance. let's not deprecate this.
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.
Is this an API that is commonly used in your projects @myuwono? It's an API I personally find kind-of strange on Option
, even on List
I think it's not commonly used 🤔
I am having a hard time thinking of a good use-case. I hope that Option<Any>
is an extremely rare case 😁
Otherwise inheritance rules should apply? 🤔
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.
Similarly to Lists, this is useful for a call that returns a sealed type @nomisRev. For instance if a database call returns Option<Document>
where document is a sealed class with many subtypes, and we are interested in only one of them e.g. Option<Document.ExternalMetadata>
.
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.
Right, you need it for narrow
'ing. So an Option
alternative to as?
.
Since this only makes sense for Option
, lets keep it 👍
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 for the feedback, @myuwono! I have reverted the deprecation in this commit
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.
Couple of thoughts, and nits. We should do a pass for the contracts in a subsequent PR, I think we might have missed some.
I'm going to approve, we can keep discussion open with @myuwono and make adjustments later on
For anyone reading this, anything deprecated now can be challenged before 2.x.x release. Or can be re-introduced if needed. Please provide and share use-cases, and production usage
arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/Option.kt
Outdated
Show resolved
Hide resolved
arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/Option.kt
Outdated
Show resolved
Hide resolved
arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/Option.kt
Outdated
Show resolved
Hide resolved
arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/Option.kt
Outdated
Show resolved
Hide resolved
@@ -1029,6 +1255,14 @@ public inline fun <A> Option<A>.ensure(error: () -> Unit, predicate: (A) -> Bool | |||
/** | |||
* Returns an Option containing all elements that are instances of specified type parameter [B]. | |||
*/ | |||
@Deprecated( | |||
NicheAPI + "Prefer using option DSL or flatMap", |
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.
Is this an API that is commonly used in your projects @myuwono? It's an API I personally find kind-of strange on Option
, even on List
I think it's not commonly used 🤔
I am having a hard time thinking of a good use-case. I hope that Option<Any>
is an extremely rare case 😁
Otherwise inheritance rules should apply? 🤔
arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/Option.kt
Outdated
Show resolved
Hide resolved
@Deprecated( | ||
NicheAPI + "Prefer Kotlin nullable syntax instead", | ||
ReplaceWith("getOrNull()?.takeIf(predicate)") | ||
) | ||
public inline fun findOrNull(predicate: (A) -> Boolean): 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.
Pretty crazy.. these APIs predate the introduction of takeIf
into Kotlin Std. Arrow is getting old, happy it's getting a new lack of paint 😍
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.
Temporarily blocking this PR pending the ongoing conversation with @myuwono.
@@ -867,7 +867,6 @@ public final class arrow/core/NonFatalOrThrowKt { | |||
|
|||
public final class arrow/core/None : arrow/core/Option { | |||
public static final field INSTANCE Larrow/core/None; | |||
public fun isEmpty ()Z |
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.
@franciscodr sorry for dragging this PR on so long 🙈
We need to revert the change we made to abstract fun isEmpty
in order to not break binary compatibility. The improvements we made in isSome
.
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.
No need to apologize, @nomisRev. Thanks for your thorough review of 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.
Thank you @franciscodr for this awesome PR 🙏 👏 🥳 And thanks @myuwono for the great feedback and brainstorming the new API 🎉
This PR proposes a smaller API surface for Option without compromising its functionality or feature set.
The goal of these changes is to offer APIs that are more powerful and more idiomatic to use in Kotlin. Following the signatures and naming of some other well-known APIs from Kotlin Std, or KotlinX Coroutines
Option (API Size 70 -> 21)
Foldable / Traverse (API Size 18 -> 1)
Keep
Remove
map { f(it) }
fold( { emptyMap() }, { a -> f(a).mapValues { Some(it.value) } })
map { value -> f(value)?.let { Some(it) } }.orNull()
fold
fold
map { value -> operation(initial(value), value) }.orNull()
fold({ Eval.now(null) }, { value -> operation(value, Eval.now(initial(value))) })
fold({ None to None }) { either -> either.fold<Pair<Option<A>, Option<B>>>({ Some(it) to None }, { None to Some(it) }) }
fold({ None to None }) { validated -> validated.fold<Pair<Option<A>, Option<B>>>({ Some(it) to None }, { None to Some(it) }) }
map { iterable -> iterable.fold(MA) }
flatMap { either -> either.fold({ None }, { Some(it) }) }
flatMap { validated -> validated.fold({ None }, ::Some) }
Functor / Applicative / Monad (API Size 21 -> 10)
New
Keep
None
None
Remove
fold({ false }, predicate)
ormap(predicate).getOrElse{ false }
fold({ true }, predicate)
ormap(predicate).getOrElse{ true }
getOrNull()?.takeIf(predicate)
map { left to it }
map { it to right }
map { List(n) { it } }
// There's an alternative with MonoidonDefined
to be more in line with Kotlin StdonEmpty
to be more in line with Kotlin StdSome(Unit)
map {}
Replace
Applicative/MonadError (API Size 5 -> 0)
Remove
getOrElse { f(Unit) }
orElse { f(Unit) }
map(fb).orElse { Some(fe(Unit)) }
flatMap(fb).orElse(fe)
flatMap { it.fold({ None }, { a -> Some(a) }) }
Align (API Size 7 -> 0)
Remove
Utilities (API Size 19 -> 10)
New
Keep
None
if it's null. Otherwise, returnSome
containing the valueRemove
flatMap { value }
if (this) { Some(f()) } else { None }
fold(Monoid.option(MA))
flatMap { when (it) { is B -> Some(it) else -> None } }
isNotEmpty
flatMap { fromNullable(f(it)) }
isNotEmpty
orElse
getOrNull