Ivan Brko
04/20/2020, 2:34 PMfun getSomeString(): String?
and I have a function that wraps a String (not String?) in some Response
fun getResponse(msg: String): Response
then I have a third function in which I need to return a Response and I am calling the getSomeString, if it returns a String I need to feed it to getResponse, but if it returns null I need to return some ErrorResponse object.
Now, I wanted to make this a one liner, but I'm having problems with thinking how to do it
It would be great if I could do something like this:
fun GetResponse: Response =
when(getSomeString()) {
is String message -> getResponse(message)
else -> ErrorResponse()
}
but I can't do this is String message. In my real use-case this is not a String but a data class with a lot of fields, and I could match on all those fields and then recreate the object on the right side of -> but that just doesn't seem right.
How would this usually be done in Kotlin? I am used to some other languages where this approach of naming the String would be done in is String message ->...Björn Mayer
04/20/2020, 2:41 PMgetSomeString()?.let { getResponse(it)} ?: ErrorResponse()
Jakub Pi
04/20/2020, 2:41 PM?.let
construction if you are only worried about the null check.Ivan Brko
04/20/2020, 2:42 PMIvan Brko
04/20/2020, 2:43 PMaraqnid
04/20/2020, 2:47 PMwhen
expression, that is when (val message = getSomeString())
, and then the is String
clause will permit a smart castaipok
04/20/2020, 2:47 PMwhen
statement
fun GetResponse: Response =
when(val message = getSomeString()) {
null -> ErrorResponse()
else -> getResponse(message)
}
This should smartcast message
in else caseIvan Brko
04/20/2020, 2:49 PMaipok
04/20/2020, 2:50 PMnull else
case I would prefer to use ?.let{ } ?:
Ivan Brko
04/20/2020, 2:51 PMaipok
04/20/2020, 2:51 PMif else
statementJakub Pi
04/20/2020, 2:51 PMaipok
04/20/2020, 2:53 PMfun GetResponse: Response {
val message = getSomeString()
return if(message != null) {
getResponse(message)
} else {
ErrorResponse()
}
}
Kroppeb
04/20/2020, 4:49 PM?.let{ }?:
is an anti-pattern imho. The docs tells us that we should prefer if else
but I like that you can assign inside a when
, something that isn't possible with a if
aipok
04/20/2020, 4:50 PMif else
over when
then possible.aipok
04/20/2020, 4:51 PMWhen
could generate weird output in bitecode. While if else
is straight forward.Kroppeb
04/20/2020, 4:53 PMwhen
with a single case and a an else
to become converted to a simple if
.aipok
04/20/2020, 4:53 PMIvan Brko
04/20/2020, 4:56 PM?.let{} ?:
not considered idiomatic code in general? would you see it in popular libraries and so?
I agree that if/else solution is easy to read, but I wanted to see how you would to this with fun ... =
instead of fun ... : <type> {return x}
as I find the former syntax to be nicer. That's why I like the when solution, as it is easy to read and the problem can be solved as a single expressionaipok
04/20/2020, 4:58 PMif else
since I will be sure in what will be generated in bytecode. But if I would not care about that, I would prefer to use when
over ?.let
Kroppeb
04/20/2020, 5:08 PM?.let{} ?:
is not semantically equivalent with if(it != null) else
Kroppeb
04/20/2020, 5:09 PMpsh
04/20/2020, 6:05 PMfun getResponse() = Response.from(getSomeString())
where I wrapped the if / else
into the response class
class Response(private val someData: String) {
companion object {
fun from(data: String?) = if (data == null)
ErrorResponse()
else
Response(data)
}
}
Extension Method
fun getResponse() = getSomeString().toResponse()
and then pulled the if / else
into an extension method
fun String?.toResponse() : Response = if (this == null)
ErrorResponse()
else
Response(this)