Kotlin-generated nested anonymous objects do not work as expected.
Consider the following Java code creating a lazy int range generator
package dummy.kt.jpype;
import java.util.Iterator;
public class IterablesJava {
public static Iterable<Integer> intRange(int min, int max) {
return new Iterable<Integer>() {
@Override
public Iterator<Integer> iterator() {
return new Iterator<Integer>() {
private int x = min;
@Override
public boolean hasNext() {
return x < max;
}
@Override
public Integer next() {
return x++;
}
};
}
};
}
}
and its Kotlin equivalent:
// file named Iterables.kt => Java class is named IterablesKt
package dummy.kt.jpype
fun intRange(min: Int, max: Int): Iterable<Int> =
object : Iterable<Int> {
override fun iterator(): Iterator<Int> =
object : Iterator<Int> {
private var x = min
override fun hasNext(): Boolean = x < max
override fun next(): Int = x++
}
}
Then, the following Python script using both intRange
methods from Python:
import jpype
import jpype.imports
import jpype
import jpype.imports
# starting jvm
from dummy.kt.jpype import IterablesJava, IterablesKt
iterable = IterablesJava.intRange(1, 10) # works (calling the Java version)
iterator = iterable.iterator() # works
print(iterator.next()) # 1
iterable = IterablesKt.intRange(1, 10) # works (calling the Python version)
iterator = iterable.iterator() # AttributeError: 'java.lang.Object$Anonymous' object has no attribute 'iterator'
print(iterator.next()) # not executed
fails when executing the Kotlin version of intRange
.
By inspecting the code, I'd say that JPype is struggling in correctly managing nested anonymous objects when the corresponding code is generated by Kotlin.
By inspecting the bytecode, I also note that the object returned by iterable.iterator()
should not be of type java.lang.Object$Anonymous
-- as reported by the exception message --, but rather IterablesKt$intRange$1$iterator$1
(I guess).
-
Re-compile the JVM code by
./gradlew shadowJar
- This should create a fat jar containing both the Java- and Kotlin-based implementations of
intRange
inbuild/libs
- First run make take a while since Gradle and dependencies should be downloaded
- This should create a fat jar containing both the Java- and Kotlin-based implementations of
-
Restore Python dependencies via
pip install -r requirements.txt
-
Run the
main.py
script viapython main.py