Stylianos Gakis
10/17/2023, 5:23 PMeither {} block, I wanted to instead of ensuring that something is not null, something like ensureNull which doesn’t exist of course 😄
My use case was that I do this
val userError: Error? = response.userError
ensure(userError == null) {
ErrorMessage(userError!!.message) // not getting smart-cast to userError being non-null here in order to be able to access `message` without a `?` or a `!!`
}
There’s no smart-contract that ensure can use to ensure not only that the condition is true if the function returns, but also that the condition is not true if the function goes inside the raise block, correct?Stylianos Gakis
10/17/2023, 7:12 PM@OptIn(ExperimentalContracts::class)
public inline fun <Error, B : Any> Raise<Error>.ensureNull(value: B?, raise: B.() -> Error): B? {
contract {
callsInPlace(raise, InvocationKind.AT_MOST_ONCE)
returns() implies (value == null)
}
return if (value == null) value else raise(raise(value))
}
Where you can propagate the right non-null B into the raise block by changing the signature of it, but then you gotta use that B which comes as the received of the lambda, and don’t get the nice smart-casting.
Also you gotta add this new function, and place it in the right spot etc of course.
At that point, maybe my best and most easy to the eye approach is to just do
val userError: Error? = response.userError
if (userError != null) {
raise(ErrorMessage(userError.message))
}
And I’m good. I get the right casting inside the if lambda, and the right assumption after the lambda is over, that userError is in fact nullable there.Alejandro Serrano.Mena
10/18/2023, 8:27 AMensureNotNull on top of ensureAlejandro Serrano.Mena
10/18/2023, 8:28 AMensureNull, but given that it's not as commonly used as ensureNotNull, we decided it would pollute the namespace more than help (but we're open to discussion about this if several people find this function useful)Stylianos Gakis
10/18/2023, 9:21 AMdata class Foo(
data: Bar?
userError: Baz?
)
And I want to short circuit if userError is not null, and then I also can do ensureNotNull on data
I'm not sure it's useful enough to pollute the API of arrow here, so I would not be one to suggest to add it, but I'm leaving my use case here just in case other people have their own opinions on it too.simon.vergauwen
10/18/2023, 11:08 AMensureNull today too 😅
I think it's a different way of modelling, I think when we designed these APIs we expected. fun validate(str: String): Either<ParsingFailure, Unit> but I'm encountering fun validate(str: String): ParsingFailure? (returns null if successfull).
So it's using null as a success value, kind of unexpected 😅 Not sure if it's similar to your use-case @Stylianos Gakis but it sounds familiar.
It's also quite typical for a Java SDK to return data class Result(val success: Response?, val failure: Exception?) as you've shown above.CLOVIS
10/18/2023, 11:12 AMensure(foo == null) but I rarely do anything in the message more than printing it so I've never really felt the need for a dedicated functionsimon.vergauwen
10/18/2023, 11:13 AMensure(foo == null) was sufficient, in my case I slightly refactored the code.Stylianos Gakis
10/18/2023, 11:13 AMensure(foo == null) but I rarely do anything in the message more than printing it so I’ve never really felt the need for a dedicated function
Yes, but our error was a type, and then we did want to do userError.message in the raise block, so we’d have to do userError!!.message to make it compile in our case. Something like thatAlejandro Serrano.Mena
10/18/2023, 11:44 AMraise to remove the !! , it doesn't add so much noise...
val userError: Error? = response.userError
if (userError != null) { raise(ErrorMessage(userError.message)) }Stylianos Gakis
10/18/2023, 11:49 AMsimon.vergauwen
10/18/2023, 11:55 AMStylianos Gakis
10/18/2023, 12:04 PMsimon.vergauwen
10/18/2023, 2:09 PMStylianos Gakis
10/18/2023, 2:11 PMsimon.vergauwen
10/18/2023, 2:13 PMAlejandro Serrano.Mena
10/18/2023, 4:04 PM