https://kotlinlang.org logo
#announcements
Title
# announcements
b

bloder

06/30/2019, 1:47 PM
Hi all, is there a more decoupled guard solution planned for Kotlin? I see Elixir`s guard as a good example and it's a solution that I really would like to use, translated to Kotlin is something like:
Copy code
fun handleError(e: Exception) if(e is NetworkException) {}

fun handleError(e: Exception) if(e is WrongUserException) {}

fun handleError(e: Exception) if(e is OtherException) {}
g

gildor

06/30/2019, 1:55 PM
Hmm, I'm not really sure how it works in Elixir, looks as some sort pattern matching, wouldn't combine this to one function work for you:
Copy code
fun handleError(e: Exception) {
  when (e) {
     is NetworkException -> ...
     is WrongUserException -> ...
     else -> ...
  }
}
b

bloder

06/30/2019, 2:04 PM
actually this
when
is exactly what I want to avoid and my main problem today... Imagine a lot of Exception checkings, this code is getting to be a modifiable and not extensible one, splitting it with functions we can improve that, separating more the code, of course we can create other solutions to handle that like I've already did (composing exceptions handling, avoiding this
when
), but I really think this guard solution is the thing that I'm looking for to solve it
g

gildor

06/30/2019, 2:08 PM
It can be some more pluggable solution, like a map of Exception to Function that handles exception, but it really depends on case. There is no pattern matching in Kotlin, so you still need some code that would map to particular exception handler
So it can be Map, or when that does matching and calls handler
Like:
Copy code
fun NetworkException.handle()
fun WrongUserException.handle()

when (e) {
  is NetworkException -> e.handle()
  is WrongUserException -> e.handle()
}
With map put all those handlers to a Map and retrieve it by exception class
b

bloder

06/30/2019, 2:15 PM
yeah sure we can map handlers, we can compose them do a lot of things about them but still have some kind o work to that, letting it to the compiler would be great in my opinion, but I really don't know the effects to Kotlin compiler a solution like that, as u said there's no pattern matching in Kotlin but I either don't know an alternative solution to that (I'm really newbie to compilers)
g

gildor

06/30/2019, 2:33 PM
I don't think that there is alternative solution with existing language features, if you have some opinion how it may be implemented and work you can propose it to #language-proposals, but it's quite a big work to just discuss it. You also can report it to Kotlin issue tracker and collect some opinions
But also, before this, I would collect some usecases first when it would require and compare with existing solutions
b

bloder

06/30/2019, 2:36 PM
Yeah I agree, is something really big and require a lot of usecases and explanations about why we would like that, just asked to know if we're already thinking in something like that.
g

gildor

06/30/2019, 2:39 PM
There is also opened issue on Kotlin issue tracker about support of multiple exceptions in catch block, maybe it can be considered in the same task, to do some semi/automatic mapping, just a rough idea
Also there is pattern matching issue, but there is no solution and Kotlin tram not sure that it would be beneficial enough, because many cases of pattern matching are already covered
b

bloder

06/30/2019, 2:44 PM
Yeah this one could be actually covered too with compiler generating a bytecode for something like:
Copy code
fun handleError_someHashCodeToConditionOne(e: Exception) {
  if (e is NetworkException) {}
}
g

gildor

06/30/2019, 2:55 PM
But how would full code look like, who would call this function
b

bloder

06/30/2019, 3:09 PM
in this solution probably we will end with all
handleError
being called, is not a good idea, maybe move that
when
logic in your first example part to compiler would be better solution, something like (but of course I still don't know the effects of it to compiler or if it's possible todo that):
Copy code
fun handleError_someHashCodeToConditionOne(e: Exception) {}

fun handleError_someHashCodeToConditionTwo(e: Exception) {}

fun main() {
// all stuffs here and now create checks to      //figure out which handleError we're going to //call and the expressions are geted from the //function declaration like
  if (e is NetworkException) handleError_someHashCodeToConditionOne(e)
  if (e is WrongUserException)
handleError_someHashCodeToConditionTwo(e)
}
Of course are missing a lot of usecases that I didn't think about it
But I'll see those issues that you mentioned to figure out if we already have a solution that is not guard to that improvement issue
g

gildor

07/01/2019, 6:16 AM
My issue with this is how it will be scoped, how map exception to particular function? is it somehow integrated with try/catch? Or you just call
handleError(somError)
and it should automatically select proper function, if second than it looks as some generic pattern matching than something related to exceptions only and not sure how such haskell-style pattern matching would work with Kotlin, it’s dramatic change of how function resolution works
b

bloder

07/01/2019, 12:06 PM
The idea is just call
handleError(somError)
and compiler decides based on function condition declarations which function will be called, the solution for that? I don't know, I see that with a giant change with pattern matching or an alternative solution as I said with some similiar solution to what compiler does with extension functions (get the written function and generate bytecode to other function struct based on the original)
p

Pavlo Liapota

07/01/2019, 12:38 PM
So instead of writing a function with
when
like @gildor suggested you want to add some very special syntax to a language, so that compiler can generate this function for you? Does this worth it? Especially if this most probably will be limited that all these functions should be placed in the same file (like for sealed classes) as it may be hard to find all implementations otherwise.
g

gildor

07/01/2019, 1:05 PM
And also not really useful, because you cannot handle more than one class by the same function, there is just no syntax to express it, otherwise it would require union types support
I can unnderstand that it you have background of the language that has such type of pattern matching it may look natural, but problem that Kotlin has completely different function resolution strategy, and it's just impossible to change like you suggesting, because it will break existing code. One more thing, Kotlin already have overloading of functions by param type, so your proposal doesn't require generation of different functions for different type, only type matching on call site (will be Invoked function with most specific type)
b

bloder

07/01/2019, 1:59 PM
Actually I'm looking for a elegant and extensible solution for that, I've already thought in some things like: Mapping, Composing, Create a pre processor to handle that, but a language solution sounds more natural and pretty and I understand pattern matching is not something to solve this problem in specific but change completely the way to develop things in Kotlin, I'm not proposing anything here, just to know if someone thought about a solution for that in language level.
and if thought, the considerations of the community about it.
g

gildor

07/01/2019, 2:03 PM
I think there is nothing more flexible and extenaible than explicit mathching using
with
b

bloder

07/01/2019, 2:14 PM
but how to match it correctly when u have a "generic type", in some place we need to make a check to handle the correct type being an explicit checking or an implicit, but maybe the features of
when
implies us to use that in the end being easier to read and understand but being less extenaible.
p

Pavlo Liapota

07/01/2019, 2:24 PM
What do you mean by explicit/implicit check? Both in your example and in suggested
when
there is an explicit check for an argument type. And why do you consider
when
to be less extensible?
b

bloder

07/01/2019, 2:39 PM
What I mean by implicit is some solution like mapping handlers, that I think it's better. When you for example have a function that handle error cases by checking its type like:
Copy code
fun handleError(e: Exception) {
  when(e) {
    is NetWorkProblem -> {}
    is OtherProblem -> {}
  }
}
and you need to put some other handling on this solution you're actually modifying your code instead of extending it, in some time you will figure out that you've created a giant solution just to check which type is your error, one another good example is consuming states from a state machine with
when
, I've created an alternative way to supply that but I'm still not 100% satisfied with that. ( https://github.com/bloderxd/result#error-cases-with-composition )
p

Pavlo Liapota

07/01/2019, 2:53 PM
Do you know about arrow library? I didn’t use it but maybe you will find what you want there. For example, https://arrow-kt.io/docs/arrow/core/try/
b

bloder

07/01/2019, 2:56 PM
Yeah, I've already saw it, it's a good library to functional development but in the end we have the same issue.
🤷‍♂️ 1
g

gildor

07/01/2019, 3:22 PM
I'm really not sure how Result is helpful in this and how it make it more readable or extandable.
I'm still think that nothing wrong with extending error handling using when, it's especially work good with sealed class instead of just an exception, because you can write exhausted when, so it will be compile type check that you handle all the cases
👍 1
b

bloder

07/01/2019, 3:37 PM
yeah sure, you can have type checking with sealed class but in the end we end up in the same case when we check which class is, but probably avoid it is something that is not considered by language and the community, thank you for your considerations about it.
2 Views