https://kotlinlang.org logo
#arrow
Title
# arrow
s

Stylianos Gakis

10/17/2023, 5:23 PM
A slight inconvenience, but in an
either {}
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
Copy code
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?
Of course trivial to make your own
Copy code
@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
Copy code
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.
a

Alejandro Serrano.Mena

10/18/2023, 8:27 AM
the problem here is that nullability contracts are treated in a special way by the compiler, you cannot just say "if this returns this general condition is true"; this is why we need a special
ensureNotNull
on top of
ensure
we could in fact include
ensureNull
, 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)
s

Stylianos Gakis

10/18/2023, 9:21 AM
Yup as I was playing with this I did realize that the simple if check is just convenient enough especially considering it's not that often that I need this. The reason I started with this is that we have an API that responds with
Copy code
data 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.
s

simon.vergauwen

10/18/2023, 11:08 AM
Funnily enough, working in a client codebase I came across a use-case for
ensureNull
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.
c

CLOVIS

10/18/2023, 11:12 AM
I often use
ensure(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
s

simon.vergauwen

10/18/2023, 11:13 AM
So far
ensure(foo == null)
was sufficient, in my case I slightly refactored the code.
s

Stylianos Gakis

10/18/2023, 11:13 AM
> I often use
ensure(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 that
a

Alejandro Serrano.Mena

10/18/2023, 11:44 AM
to be honest, in this case I would use an explicit
raise
to remove the
!!
, it doesn't add so much noise...
Copy code
val userError: Error? = response.userError
if (userError != null) { raise(ErrorMessage(userError.message)) }
s

simon.vergauwen

10/18/2023, 11:55 AM
@Alejandro Serrano.Mena @Stylianos Gakis we should probably get that repo on the website as a large real world example!
s

Stylianos Gakis

10/18/2023, 12:04 PM
I’d be super happy to see that happen! Being a full app does make it somewhat hard perhaps for some folks to navigate the app, but at the same time that’s maybe a good thing, it shows the flexibility of arrow regarding using it in the places where it fits, and not necessarily something that every single thing in your entire app has to use. We do use arrow in pretty much 100% of the “UseCase/Repository” classes, basically things that our Presenters/ViewModels depend on. And I say “pretty much 100%” since I know that’s the case for all code that has been written in the past ~1-2 years ever since I brought Arrow in to the repo, but there are still some outliers which I would migrate in an instant if we ever touch them 😅
s

simon.vergauwen

10/18/2023, 2:09 PM
I think that's great. There is plenty of small examples already out there, but a larger example is harder to find. Especially one that has been going on for several years.
🦠 1
s

Stylianos Gakis

10/18/2023, 2:11 PM
Lmk if you need any help from my side, would be happy to help!
s

simon.vergauwen

10/18/2023, 2:13 PM
@Alejandro Serrano.Mena I think we should introduce a new page for this on the website. WDYT? Perhaps under "Community" we can add an "Example Projects", or "Examples" section? We can also add Ktor Arrow Examples, your Weather App, HedvigInsurance App, and others
a

Alejandro Serrano.Mena

10/18/2023, 4:04 PM
there's a page for this in Design https://arrow-kt.io/learn/design/projects/
thank you color 1
2 Views