Refer to extension function defined as a member; inlining `with` - kotlin

Say I have the following:
object Foo {
fun Int.negate() = -this
fun negateInt(n: Int) = -n
}
I can call the extension method negate on Foo by using with:
fun main() {
println(with(Foo) { 5.negate() }) // prints -5
}
I can call the other method by calling it on the Foo object:
fun main2() {
println(Foo.negateInt(5)) // prints -5
}
I think with(Foo) { 5.negate() } is syntactically a bit on the heavy side compared to Foo.negateInt(5) when the body is just a single invocation. I can't find a more compact way to perform this call though. I had hoped that I could do Foo::negate to get a function (Int) -> Int where this has been lifted to be an argument, just like I can do for normal non-extension methods. For example, val f = Int::toString will give me a function (Int) -> String such that f(42) is equivalent to 42.toString(). If I could do that, then I could write (Foo::negate)(5) which is still heavy, but less heavy than with(Foo) { ... }.
Is there really no way to explicitly refer to an extension method defined as a member?

Yes, you can refer directly. For that you just need to import the extension function to your current package:
import Foo.negate
Then in your code you can do:
println(5.negate())

Maybe this is the best you can get
class Bar(val offset: Int) { fun Int.negate() = offset - this }
fun main() {
val bar = Bar(42)
bar.run { 5.negate() }
}

Related

How to call constructor default lambda using Kotlin Refelction?

Trying to call lambda provided by MyClass constructor using Kotlin Reflection.
data class MyClass(
var magic:Int=2,
var lambdaValue: ()->String = { //trying to call this lambda from reflection
"Working"
},
)
fun main(args: Array<String>) {
val clazz=MyClass::class
val obj=clazz.createInstance()
val kProperty=clazz.memberProperties
clazz.constructors.forEach{cons-> // for each construtor
cons.parameters.forEach{ parameter-> // looping through constructor parameters
val property=kProperty.find { it.name==parameter.name } // finding the exact property
print(parameter.name+" : ")
if(parameter.type.arguments.isEmpty()) // if empty Int,Float
{
println(property?.get(obj))
}else{
println(property?.call(obj)) // unable to call lambda
}
}
}
}
property.call(obj) returns Any which is not invokable. Any solution?
Expected:
magic : 2
lambdaValue : Working
Frankly speaking, I'm not sure what was your idea behind parameter.type.arguments.isEmpty(). It seems unrelated to what you try to do.
If we have a value of the property already, we can simply check its type and if its is a function then invoke it:
val value = kProperty.find { it.name==parameter.name }!!.get(obj)
print(parameter.name+" : ")
when (value) {
is Function0<*> -> println(value())
else -> println(value)
}
I think usefulness of such a code in generic case isn't very high. This code doesn't know what is the function and if it is going to return a value or perform some action, etc. Maybe in your specific case it is more useful.

Is it possible to null T or 'this' at the end of generic function for Kotlin?

I have in my project a listener. It is assigned to drawerLayout. I would like to in lambda function remove it and null it at once (sequentially). Is it possible to null T or this at the end of generic function.
Here is my code:
// Usage
actionBarListener?.let {
drawerLayout.removeDrawerListener(it) // remove listener
actionBarListener = null // null it
}
// Usage expected
actionBarListener.releaseAndSetNull {
drawerLayout.removeDrawerListener(it) // remove listener and null it
}
// Generic
fun <T> T?.releaseAndSetNull(block: (T?) -> Unit) = apply {
this?.apply { block.invoke(this) }
this = null // Error: variable expected
}
As Ivo Beckers said, this function would only work on vars, i.e. KMutableProperty0<T>. So you could write an extension on KMutableProperty0<T?>, and use reflection to set it, if you don't mind using reflection, that is.
inline fun <T: Any> KMutableProperty0<T?>.releaseAndSetNull(block: (T?) -> Unit) {
block(this.get())
this.set(null)
}
// or if you don't want the block to be called if the property is null:
inline fun <T: Any> KMutableProperty0<T?>.releaseAndSetNull(block: (T) -> Unit) {
this.get()?.run(block)
this.set(null)
}
Then suppose you have a property:
var foo: Int? = 10
You can do:
::foo.releaseAndSetNull { println("Foo: $it") }
// or if foo belongs to someObject
someObject::foo.releaseAndSetNull { println("Foo: $it") }
Looking at the generated bytecode, the way this is implemented (which is subject to change) is that each unique property referred to by a property reference in this way causes an inner class to be generated. The inner class will then have get and set methods that do their jobs with little extra cost - as they can just set the right property directly. So really the main cost is the extra inner class that is generated.
I can think of several reasons why this could never work.
First of, the generic function doesn't know if this is a var or val. And this functionality could only works on a var
Likewise, it can't know if it's nullable, that's also a requirment.
Furthermore, it can even be the case that it's not a variable that's calling the function.
Like say you have
fun getActionBarListener() {
return actionBarListener
}
Then somewhere else you could do
getActionBarListener().releaseAndSetNull {
drawerLayout.removeDrawerListener(it) // remove listener and null it
}
How do you expect that to work?
Or even anonymous objects could call this function.

Kotlin - Automatically match overriden function type?

I'm trying to write a function that is essentially a wrapper method around some other functionality, for instance, some logging function.
I've tried several combinations of inline, generic, reified, etc., but nothing seems to work.
My function looks like this:
fun log(note: String, block: () -> Unit): () -> Unit {
print(note)
return block
}
My idea here is to perform some simple operation on the incoming note, and then just return that incoming function to be used as it was originally.
However, I want to do this around overridden functions like so:
override fun onClick(clicked: View) = log("Green Button") {
// here the regular onClick functionality goes
}
Here, I get an error "Return type is () -> Unit, which is not a subtype of overridden". This makes sense enough, as the function signatures do not match.
However, when I do this with other random functions:
fun test() = log("foo") { ... }
fun otherTest(a: String, b: Int) = log("bar") { ... }
I get no errors, and the interpreter somehow seems fine with this. I also tried looking at something like GlobalScope.launch to take that approach, but I couldn't figure it out.
Is what I'm trying to do possible? If not, is there something close?
I think
inline fun log(note: String, block: () -> Unit): Unit {
print(note)
return block()
}
should do what you want. It can be generalized to
inline fun <T> log(note: String, block: () -> T): T {
print(note)
return block()
}
I get no errors, and the interpreter somehow seems fine with this.
Why is that surprising? Those functions just return () -> Unit. If you do e.g.
fun test() = log("foo") { print("bar") }
then calling test() won't print bar; calling test()() will.
Tell me if my understanding is wrong. This is my approach
Extension function:
fun View.onClickWithLog(str: String, l: () -> Unit) {
setOnClickListener { Log.d("LogTag", str); run(l) }
}
Usage (from Activity):
btnTest.onClickWithLog("My Button String"){
Log.d("Actions from Activity", "Content")
finish()
}
and the output is
D/LogTag: My Button String
D/Actions from Activity: Content
which prints your note first, and execute the actions in the lambda expression.
When you use the = operator to assign something to a fun, the expression on the right hand side is supposed to return the return type of that fun
The original fun onClick(clicked:View) : Unit has return type Unit. When you write
override fun onClick(clicked:View) = ... , the ... is what you get when you call onClick(v) so it should be a Unit instead of a View -> Unit (Not even () -> Unit as in your code)
Take a simpler example. Let say you have fun sum(a:Int,b:Int) : Int. When you write override fun sum(a:Int,b:Int) = ... , ... must be an Int instead of a (Int,Int) -> Int since you expect to get an Int immediately when you call sum(a,b). If you somehow got a let say
val someOtherWayToSum : (Int,Int) -> Int = {...}
and want to use it, you can write
override fun sum(a:Int,b:Int) = someOtherWayToSum(a,b)
In your case, you better just do
override fun onClick(clicked:View){
/* some operation (e.g your log)*/
/* the regular onClick functionality */
}
since you are overriding it and implementing its regular functionality right there anyway.

Why is subtype function overloading not possible with Kotlin sealed classes?

Let's say I have sealed class I'm using for a server response:
sealed class Response{
class Success: Response()
class ErrorA: Response()
class ErrorB: Response()
}
And a bogus response:
fun getResponse(): Response{
val r = Random()
return when (r.nextInt(3)) {
0 -> { Response.Success() }
1 -> { Response.ErrorA() }
2 -> { Response.ErrorB() }
else -> { throw IllegalStateException() }
}
}
And I want to handle the response. I currently could use something like this:
fun handle(response: Response) = when (response) {
is Response.Success -> { handle(response) }
is Response.ErrorA -> { handle(response) }
is Response.ErrorB -> { handle(response) }
}
Which the compiler will then ensure handles all cases. An awesome feature!
Why, though, could I not do something like this:
class ResponseHandler(){
fun handle(success: Response.Success) {}
fun handle(error: Response.ErrorB) {}
fun handle(error: Response.ErrorA) {}
}
and call
ResponseHandler().handle(response)
This achieves the same thing but does not compile, my question is this: in the same way that the compiler ensures, at runtime, that all cases are handled in a when statement, why can the same logic not be applied to method overloading?
Any information or referrals to further reading would be hugely helpful. Thanks
In principle it could be done (essentially by auto-generating the handle(response: Response) = when ... method). But I don't think it's ever likely to be. Overloading in Kotlin works basically the same as in Java/Scala/other JVM languages and introducing a major difference for so little benefit doesn't looks like a good idea (of course this doesn't apply to when which is Kotlin-specific).
If you want it, you can just define the same fun handle(response: Response) inside ResponseHandler (and make the other handle methods open so it's actually useful).
This problem can be broke down to this simplified example:
fun calc(i: Int) = i * 2
fun calc(d: Double) = d * 2
fun main(args: Array<String>) {
val i: Number = 5
calc(i)
}
You have two specialized methods that take an Int and Double respectively. Your value is of type Number (supertype of both, Int and Double). Although i obviously is an integer, your variable has a type Number, which cannot be an argument to either calc(i: Int) or calc(d: Double).
In your case, you get a Response and want to invoke one of the overloaded methods, none of which takes a Response directly.

How to specify "own type" as return type in Kotlin

Is there a way to specify the return type of a function to be the type of the called object?
e.g.
trait Foo {
fun bar(): <??> /* what to put here? */ {
return this
}
}
class FooClassA : Foo {
fun a() {}
}
class FooClassB : Foo {
fun b() {}
}
// this is the desired effect:
val a = FooClassA().bar() // should be of type FooClassA
a.a() // so this would work
val b = FooClassB().bar() // should be of type FooClassB
b.b() // so this would work
In effect, this would be roughly equivalent to instancetype in Objective-C or Self in Swift.
There's no language feature supporting this, but you can always use recursive generics (which is the pattern many libraries use):
// Define a recursive generic parameter Me
trait Foo<Me: Foo<Me>> {
fun bar(): Me {
// Here we have to cast, because the compiler does not know that Me is the same as this class
return this as Me
}
}
// In subclasses, pass itself to the superclass as an argument:
class FooClassA : Foo<FooClassA> {
fun a() {}
}
class FooClassB : Foo<FooClassB> {
fun b() {}
}
You can return something's own type with extension functions.
interface ExampleInterface
// Everything that implements ExampleInterface will have this method.
fun <T : ExampleInterface> T.doSomething(): T {
return this
}
class ClassA : ExampleInterface {
fun classASpecificMethod() {}
}
class ClassB : ExampleInterface {
fun classBSpecificMethod() {}
}
fun example() {
// doSomething() returns ClassA!
ClassA().doSomething().classASpecificMethod()
// doSomething() returns ClassB!
ClassB().doSomething().classBSpecificMethod()
}
You can use an extension method to achieve the "returns same type" effect. Here's a quick example that shows a base type with multiple type parameters and an extension method that takes a function which operates on an instance of said type:
public abstract class BuilderBase<A, B> {}
public fun <B : BuilderBase<*, *>> B.doIt(): B {
// Do something
return this
}
public class MyBuilder : BuilderBase<Int,String>() {}
public fun demo() {
val b : MyBuilder = MyBuilder().doIt()
}
Since extension methods are resolved statically (at least as of M12), you may need to have the extension delegate the actual implementation to its this should you need type-specific behaviors.
Recursive Type Bound
The pattern you have shown in the question is known as recursive type bound in the JVM world. A recursive type is one that includes a function that uses that type itself as a type for its parameter or its return value. In your example, you are using the same type for the return value by saying return this.
Example
Let's understand this with a simple and real example. We'll replace trait from your example with interface because trait is now deprecated in Kotlin. In this example, the interface VitaminSource returns different implementations of the sources of different vitamins.
In the following interface, you can see that its type parameter has itself as an upper bound. This is why it's known as recursive type bound:
VitaminSource.kt
interface VitaminSource<T: VitaminSource<T>> {
fun getSource(): T {
#Suppress("UNCHECKED_CAST")
return this as T
}
}
We suppress the UNCHECKED_CAST warning because the compiler can't possibly know whether we passed the same class name as a type argument.
Then we extend the interface with concrete implementations:
Carrot.kt
class Carrot : VitaminSource<Carrot> {
fun getVitaminA() = println("Vitamin A")
}
Banana.kt
class Banana : VitaminSource<Banana> {
fun getVitaminB() = println("Vitamin B")
}
While extending the classes, you must make sure to pass the same class to the interface otherwise you'll get ClassCastException at runtime:
class Banana : VitaminSource<Banana> // OK
class Banana : VitaminSource<Carrot> // No compiler error but exception at runtime
Test.kt
fun main() {
val carrot = Carrot().getSource()
carrot.getVitaminA()
val banana = Banana().getSource()
banana.getVitaminB()
}
That's it! Hope that helps.
Depending on the exact use case, scope functions can be a good alternative. For the builder pattern apply seems to be most useful because the context object is this and the result of the scope function is this as well.
Consider this example for a builder of List with a specialized builder subclass:
open class ListBuilder<E> {
// Return type does not matter, could also use Unit and not return anything
// But might be good to avoid that to not force users to use scope functions
fun add(element: E): ListBuilder<E> {
...
return this
}
fun buildList(): List<E> {
...
}
}
class EnhancedListBuilder<E>: ListBuilder<E>() {
fun addTwice(element: E): EnhancedListBuilder<E> {
addNTimes(element, 2)
return this
}
fun addNTimes(element: E, times: Int): EnhancedListBuilder<E> {
repeat(times) {
add(element)
}
return this
}
}
// Usage of builder:
val list = EnhancedListBuilder<String>().apply {
add("a") // Note: This would return only ListBuilder
addTwice("b")
addNTimes("c", 3)
}.buildList()
However, this only works if all methods have this as result. If one of the methods actually creates a new instance, then that instance would be discarded.
This is based on this answer to a similar question.
You can do it also via extension functions.
class Foo
fun <T: Foo>T.someFun(): T {
return this
}
Foo().someFun().someFun()