reflect_on_lambda_body_.kt
# reflect
h
reflect_on_lambda_body_.kt
d
You could get the java class of the lambda and then use a bytecode analyzing library to look for an invocation bytecode and look at which method is being invoked.
h
Thanks @diesieben07 do you have any recoomendation concerning such a library? I’ve never worked with bytecode directly.
d
https://asm.ow2.io/ is pretty much the standard
h
Thanks, I’ll have a look.
d
However, the question is if this is really necessary. Does it have to be a lambda?
h
I’m building a visualization library and it would make it more convenient. See 2nd example in https://github.com/holgerbrandl/kravis#iterators for an example, where I’d like to apply it. If possible the axis labels should be determined from the lambdas such as
{ heightCm }
. Currently the user has to specify them again.
d
Okay, I see. You could require users to pass in a reference instead:
ggplot(x = Person::heightCm)
That way you can extract the name.
h
That’s a good idea as well. Though, it involves duplication of the type in case of multiple attributes, that’s why I also still like the lambda-style syntax.
Is there any way to reduce is to something like
x = ::conservation
? The type context is known because of refied generics.
In other words, can i use a property reference without prefixing it with the type itself?
Copy code
import krangl.SleepPattern
import krangl.sleepPatterns
import kravis.GGPlot
import kravis.ggplot
import kotlin.reflect.KProperty1

inline fun <reified T> Iterable<T>.buildPlot(
     x: KProperty1<T, *>,
     y: KProperty1<T, *>
): GGPlot {
    val map = map { x.get(it) to y.get(it) }

    // later convert data to actual plot

    return ggplot()
}

val basePlot = sleepPatterns.buildPlot(
    x = SleepPattern::conservation,
    y = SleepPattern::bodywt
)

// nicer but not legit:

val basePlot = sleepPatterns.buildPlot(
    x = ::conservation,
    y = ::bodywt
)
d
I don't think that is possible, unless you have a reference to the class available. In that case you could do this:
Copy code
fun <T : Any> buildPlot(referenceExtractor: (T).() -> KProperty0<*>) = TODO()
Called like this:
Copy code
buildPlot<MyClass> { ::propertyOfMyClass }
But that then requires an instance of
MyClass
inside
buildPlot
to call the lambda. And it is really just starting to bend the language in ways it's not designed to go
h
Actually, since it’s an extension on
Iterable<T>
I have tons of instances of T. It’s a great solution which I would have never found myself, thanks a lot. 🙂
Hope to meet you at KotlinConf!
d
Unfortunately not. Don't have the money and/or time. Still a poor apprentice 😄
Some day though!
h
Next time then!