Is there any way to omit the `kotlin.` from `kotli...
# android
a
Is there any way to omit the
kotlin.
from
kotlin.runCatching { ... }
? I always have to import the second option if I want the shorter one.
c
That's how importing in Kotlin works.
What's wrong with it?
a
it should import the kotlin’s
runCatching
and use it. what it does is equivalent to writing full class names, as opposed to importing them and using their name.
c
kotlin
is the package and you want to import a method. You can do
Copy code
import kotlin.runCatching
a
I’m not sure If the problem has been communicated properly. I’m not reporting that imports are not working. I have an IDE problem. The problem is when you type
runCa
and then press tab, it inserts
kotlin.runCatching
and not
runCatching
(which will work file if it does place that). no imports are needed.
c
then this is not the right channel. that would rather be an Android studio plugin issue or kotlin plugin issue.
p
Why do people use runCatching but don’t do generic try-catch(exception)? I’d like that runCatching function to be deprecated as it encourages bad code
c
but thats what
runCatching
is doing just wrapping the execution result in a
Result
.
I just encapsulates the try/catch inside a function. what is “bad code” with this approach? 🤔
a
@Paul Woitaschek Because it’s a generic Kotlin function that returns a Result. You can use that (it’s more of a functional approach called railway programmgin)
p
I would not use it as a return type. It has no type of the exception so the caller has no really sane way of handling it. And if you have a bug in there, maybe sth like:
Copy code
runCatching {
  val name = parseAge(input)
  uploadName(name)
}
You usually want to catch a very specific failure. And if now
parseAge
is throwing an exception that gets wrapped in the result type as well. Ive seen a lot of bad code around the result type
2
a
+1. Unless you're using
runCatching
to get a result to pass to
Continuation<T>.resumeWith(result)
it's probably not helping your design
a
We’re mostly using it instead of try catch. It actually has no difference with try catch, except that you don’t need to specify the exception that you’re catching (which is mostly an API error)
(inside view models)
something like this:
Copy code
runCatching {
    getData()
}.fold({
    data ->
    updateState(data)
}, {
    error ->
    updateStateToFailed(error)
})
I’m not sure how this can hurt the design. can you elaborate?
a
Except now you're back to railway operator chains to write any of your code. Kotlin moves away from that style of Single/Maybe for async APIs in favor of coroutines and writing plain Kotlin code instead of reinventing or filling in for missing language features with bespoke library API.
Introducing it again by way of using runCatching in place of try/catch is kind of snatching defeat from the jaws of victory there
The code pasted above will treat cancellation improperly in a suspend function outside of specific circumstances around it, and is more difficult to read than a try/catch
☝️ 1
p
An option would be to use sth like https://github.com/slackhq/EitherNet and re-throw if it’s
UnknownFailure
a
That's not to deflect from the IDE bug you're noting, which, yes, does look like a real bug and I've hit it too 🙂
p
The code pasted above will treat cancellation improperly in a suspend function outside of specific circumstances around it
Yep, that’s breaking structured concurrency and might bring you in really unexpected lands
a
You probably don't want to
updateStateToFailed
with any CancellationException that comes through, and you probably do want to rethrow it even then to continue handling cancellation properly
This article from quite some time ago on why checked exceptions have issues describes some of why using
Result<T>
as a common return type is an awkward design fit: https://www.artima.com/articles/the-trouble-with-checked-exceptions
Result<T>
turns all exceptions into checked exceptions (the developer has to deal with them somehow at every level rather than letting them unwind the stack to a point that can make a semantically relevant decision about it) except without type safety of the exceptions themselves, and then you swallow a spider to catch the fly by adding railway operators to try to solve an ergonomic problem you created
p
It would make sense to have a compiler warning if runCatching was used in a suspend function
a
@Adam Powell I agree with your point (on returning results), I was explaining a reason for the IDE that imports the wrong
runCatching
. the above example is not in a suspend function at all. It is inside a view model that is calling some suspend function, in its own scope. Doing a try-catch is almost exactly the same, but I think runCatching look a bit cleaner. If you do not want to catch all errors, you can always use the good old try-catch. runCatching has some nice apis too. If you really don't care about the result of something and want a nullable value, you can use
runCatching { ... }.getOrNull()
which has a more Kotlin-ish API (like Lists and ...).