Elvis Operator


#1

I want to execute a msg if the location is null, and another msg if it is not null, so I’m trying use the elvis-operator as a?.let{} ?: run{} statement, but the run part is not reachable, and it tells me it is not required nor non-nullable!

The function I’m getting the error with, is:

getLocation(
           context,
                { location ->
                    location?.let {
                        msg = ("As of: ${Date(it.time)}, " +
                                "I am at: http://maps.google.com/?q=@" +
                                "${it.latitude}, ${it.longitude}, " +
                                "my speed is: ${it.speed}")
                    } ?: run { . // Getting error here
                        msg = "Sorry, it looks GPS is off, no location found\""
                    }

                    sendSMS(
                            context,
                            address,
                            msg,
                            subId
                    )
                }
        )

Th getLocation function is:

object UtilLocation {
    private lateinit var l : Location

    @SuppressLint("MissingPermission")
    fun getLocation(context: Context, callback: (Location) -> Unit) {
        fusedLocationClient = LocationServices.getFusedLocationProviderClient(context!!)

        fusedLocationClient.lastLocation
                .addOnSuccessListener { location : Location? ->
                    this.l = location!!
                    callback.invoke(this.l)
                }
    }
}

#2

I would recommend to specify the return type of the function as nullable. If it doesn’t solves the problem I have no clue.


#3

If I see this right, location in the callback can never be null, because of the callbacks type (Location) -> Unit, try (Location?) -> Unit. Another problem is that you will never call your callback with null. You pass this.l which is not nullable. Instead if LocationServices.getFusedLo... returns null you will run into a NPE.


#4

Apart from the issues already mentioned, why do you want to use safe call operator, elvis operator, let and run if the same can be done with a basic if-else. And would be way more expressive that way.

    if(location != null){
        msg = ("As of: ${Date(location.time)}, " +
                "I am at: http://maps.google.com/?q=@" +
                "${location.latitude}, ${location.longitude}, " +
                "my speed is: ${location.speed}")
    }else{
        msg = "Sorry, it looks GPS is off, no location found\""
    }

Anyway, if you want to use elvis operator, your value should be a return value, like

    val msg = loc?.let {
        "foo"
    } ?: "bar"