Hey there. I've idea that can be really useful (de...
# language-proposals
k
Hey there. I've idea that can be really useful (definitely on Android). Difficult to explain this, but have a sample:
Copy code
interface Animal

class Dog : Animal
class Cat : Animal

fun randomAnimal(callback: (Animal) -> Unit) {
    callback.invoke(Dog())
}

fun main() {
    // Directly casting parameter to specific type when
    // declaring lambda parameters
    randomAnimal { animal as Dog -> // pay your attention. Here we cast Animal to Dog
        // Do something with dog...
    }

    // Safe cast sample
    randomAnimal { animal as? Dog -> // safe cast Animal to Dog
       animal?.let { 
           // Do something with dog...
       }
    }
}
d
What is the use case of this feature? What do you want to achieve with this?
k
In android there is a lot of inheritance, and in some situations we exactly know object of what type we'll receive. For example, when creating custom BottomSheetDialogFragment, it extends DialogFragment that has method
setOnShowListener
from which we receive some
DialogInterface
object and we exactly know that this is of type
BottomSheetDialogFragment
. And we need to declare another one variable just to cast this parameter to type we want.
Copy code
setOnShowListener { dialog ->
    val bottomSheetDialog = dialog as BottomSheetDialog
}
It looks ugly for several reasons. First of all, we need to declare another one variable. It causes some problems with naming. After that we have
dialog
variable in lambda scope that is unnecessary. And if we compare the sample above with this one:
Copy code
setOnShowListener { dialog as BottomSheetDialog -> 
 // ...
}
It looks much better IMHO.
j
I'd rather see the ability to refine names in a scope like Rust. Then your example just becomes
val dialog = dialog as BottomSheetDialog
.
2
d
You don't need a new variable.
Copy code
setOnShowListener { dialog ->
    dialog as BottomSheetDialog
}
I'd also argue that this is an issue with
DialogFragment
for not giving it a more specific type.
j
But redefining means you can do things like
val input = input.toInt()
d
I am familiar with the Rust feature but I thought shadowing let's you change types, effectively providing that feature.
j
Doesn't that only work with a new scope?
🤷🏼 1
c
I'm all for this sort of functionality. I was surprised when I realized this wasn't possible...
Copy code
"12345".forEach { character as String -> 
    character.toInt()
}
Being able to redefine would be nifty too. I think Android may have it fixed now, but I know several months ago I had a number of composite views with
nonNullContext ->
scattered throughout, being able to just use
context
within that scope would have been nice.
j
The cast in that example would never succeed
c
Whoops, was assuming since the
toString()
worked that casting would work for that, but I guess not 🤷🏻‍♂️
Maybe that could be another request that could fit into contracts. Define that a class has a function which lets you map it from one type to another, if that exists then
as
would reference that function.