is it possible to throw from inside a map function...
# announcements
x
is it possible to throw from inside a map function without having to change the return type of the function to List<Any>?
so i want a map to try catch something, and in case of the catch just throw (for transactional purposes)
a
Throwing inside a map? do you mean throwing while transforming a map?
x
Copy code
fun test(): List<Any> {
    val test = listOf(1, 3, 4)

    return test.map { number -> 
               try {
                   if (number == 4) throw IllegalArgumentException("aaaa")
                   number+1
               } catch (e: Exception){
                   throw e
               }
             }
}
something like this
the reason i want to catch inside the map is because i want the number to be part of the exception (not pictured in the example)
c
Don’t have an IDE open, but probably just needs an explicit return as the catch block is resolving to a different type.
x
yep, but in reality the catch wont actually return a list of anything, it will straight up throw
r
I do have an IDE open, copied in your example and it compiles changing the return type to List<Int>
a
What should the result of the list be after catching?
x
in my IDE it might compile, but i get a red warning
r
He’s throwing it again, so it doesn’t matter.
x
Copy code
Type inference failed. Expected type mismatch: 
required:
List<Number>
found:
List<Any>
r
With that exact example?
x
you're right, im calling a handler for the exception in my local code
so another function
Copy code
fun test(): List<Number> {
    val test = listOf(1, 3, 4)

    return test.map { number -> 
               try {
                   if (number == 4) throw IllegalArgumentException("aaaa")
                   number+1
               } catch (e: Exception){
                   handle(e)
               }
             }
}

fun handle(e: Exception){
    throw e
}
this is closer to reality
r
Make
handle
return
Nothing
👍 2
Copy code
private fun handle(e: Exception): Nothing {
        throw e
    }
x
thats it! thank you!
this is the ugliest thing ive ever done btw
r
Nothing
is a bottom type - that is, it is a subtype of every type. So the nearest common supertype of
Int
and
Nothing
is
Int
. Whereas a function that has no explicit return type actually has a return type of
Unit
, and
Unit
is a normal type, so the nearest common supertype of
Int
and
Unit
is
Any
. In general
Nothing
can be used as the return type of code that will never actually return.
x
i see, but throwing is somehow kind of a reutrn, no?
i generally dont like this try catch approach to things
c
In general, I think most people in the Kotlin community would recommend you not bubbling exceptions. Instead make use of sealed types.
r
throwing isn’t returning, it’s more like goto the first matching catch block in the stack
👆 1
x
but on a normal controller where you want the user to be able to see what went wrong
what would you do? model the return type of the parent function to a certain throw? instead of bubbling up the error
c
The user would be getting a dto that either has the result they requested or another dto that holds the error information, correct?
x
yeah
c
So return a sealed class that can be one or the other.
👍 2
x
i see
r
Either<L, R>
is a generic example of this pattern that’s common in functional statically type checked languages; arrow has an implementation.
👍 2
c
Often see stuff like this in controllers.
Copy code
sealed class Example
class A : Example()
class B : Example()

fun example(): HttpResponse<Example> {
	val obj: Example = exampleService.getExample()
	return when (obj) {
		is A -> HttpResponse.ok(obj)
		is B -> HttpResponse.badRequest(obj)
	}
}
👍 1
n
still hard to reconcile everyone suggesting that "most people" in the Kotlin community would recommend this, yet there is no standard library class to help with these kinds of patterns...
c
There is the Result type, but you can’t return it from methods I think because it’s experimental.
n
Yeah, apparently there isn't a plan to standardize it, and even then, it's not really exactly what you want because it erases the type of the error
c
n
I've seen members of the kotlin team here arguing specifically against ever standardizing something similar to Result, but still encouraging people to used the sealed class style for their errors
It's very hard for me to wrap my head around that reasoning; languages that encourage this error handling style tend to provide something for it (e.g. Rust)
c
Would be interested to read more detail from the team. I really like the way Rust’s Option and Result types work. But yeah, in Kotlin I usually don’t use an equivalent of Either or Result. I tend to just create a sealed class for the particular service. I guess there’s a bit of boiler plate there, but it it allows me to handle more than just the 2 cases.
For instance, return might be one of ThingBeingRequested, IOError, ValidationIssue, etc.
n
You can put a Rust enum in a Result type, nothing is stopping you
Result just factors out the common code in this situation and provides a uniform interface; the idea that there's a successful result that you want, and some kind of error type that you don't.
c
Oh yeah definitely. Was speaking with regards to Kotlin.
n
Even if Result has some issues and won't be standardized, just look at its API, these are all things you'd want to have over and over again to use in conjucntion with said sealed types, so I don't understand why they're against standardizing it
Writing
getOr
on your sealed success/error classes for the 20th time is going to get old
c
Think it has to do with not making any mistakes that prevent them from adding in ?, !!, ??, etc. syntax sugar. Not sure how it would prevent them doing it though tbh. Result was one of the first things I reached for in Kotlin and was also surprised it wasn’t available.
n
I think they can always come back to syntactic sugar, and maybe they decide not to add it, and that may be fine as well
I don't think syntactic sugar is as important in kotlin
because exceptions are still fine, if you want to percolate up an error a significant distance
in Rust, panics are totally discouraged so you really want to make bubbling up as concise as humanly possible