-
Notifications
You must be signed in to change notification settings - Fork 65
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
ensureNotNull-alike binding scope extensions #84
Comments
I may be misunderstanding, but I think we already support this behaviour with Your example would go like this: val value = maybeGetValue()?.toResultOr { ValueMissingError }.bind() |
@kirillzh does that help? |
To clarify, I guess we can't quite use val value = maybeGetValue()
.bind()
.toResultOr { ValueMissingError }
.bind() |
Ah okay, so you want to keep it as a |
Exactly! The original proposed API for that I mentioned... val value = maybeGetValue().bind()
ensureNotNull(value) { ValueMissingError } Now as I'm thinking through it, the actual API that I am looking for roughly looks like this: inline fun <V, E> Result<V?, E>.ensureNotNull(
error: (V?) -> E,
): Result<V, E> = ensure(
predicate = { it != null },
error = error,
).map { it as V }
inline fun <V, E> Result<V, E>.ensure(
predicate: (V) -> Boolean,
error: (V) -> E,
): Result<V, E> = flatMap { if (predicate(it)) Ok(it) else Err(error(it)) } And so instead of using val value = maybeGetValue()
.flatMap {
when (it) {
null -> Err(ValueMissingError)
else -> Ok(it)
}
}
.bind() Can use val value = maybeGetValue()
.ensureNotNull { ValueMissingError }
.bind() |
I wonder if we just make a |
@michaelbull, Right now it's implemented as: public inline fun <V, E> Result<V, E>.toErrorIfNull(error: () -> E): Result<V, E> { Which returns nullable success value: val account = accountRepository.getActiveAccount()
.toErrorIfNull { AccountMissing }
.get() // Account? <--- nullable A preferred signature here would be: inline fun <V, E> Result<V?, E>.toErrorIfNull(error: () -> E): Result<V, E> Which would return non-nullable success value: val account = accountRepository.getActiveAccount()
.toErrorIfNull { AccountMissing }
.get() // Account <--- non-nullable |
@kirillzh that example signature doesn't seem to work for me: |
|
So what is the change you are requesting? |
@michaelbull, consider this snippet: fun provideResult(): Result<String?, Int> = Ok(null)
fun main() {
provideResult()
.toErrorIfNull { 50 }
.map { value ->
value.length // <- won't compile, value is nullable
}
} I would expect for |
Is there anything more that I need to do other than change the signature to facilitate that example that you've posted? |
I think it needs to change from this: public inline fun <V, E> Result<V, E>.toErrorIfNull(error: () -> E): Result<V, E> {
contract {
callsInPlace(error, InvocationKind.AT_MOST_ONCE)
}
return toErrorIf(
{ it == null },
{ error() }
)
} To this: public inline fun <V, E> Result<V?, E>.toErrorIfNull(error: () -> E): Result<V, E> {
contract {
callsInPlace(error, AT_MOST_ONCE)
}
return toErrorIf(
{ it == null },
{ error() }
).map {
@Suppress("UNCHECKED_CAST")
it as V
}
} |
Okay, I think writing it out as a |
Addressing this in #86 |
Arrow has a handy extension for eagerly returning from effect with an error if a value is null -
ensureNotNull
. Would be very helpful to have a similar extension here, right now need to rely on fairly nestedflatMap
:vs
The text was updated successfully, but these errors were encountered: