いつもありがとうございます。
http://jenetics.io/
こちらにあるJavaのコードをkotlinで記述しようと思っています。
Kotlin
1// 2.) Definition of the fitness function. 2fun eval(gt: Genotype<BitGene>): Int { 3 return gt.chromosome 4 .`as`(BitChromosome::class.java) 5 .bitCount() 6} 7 8fun main(vararg args: String) { 9 10 // 1.) Define the genotype (factory) suitable for the problem. 11 val gtf = Genotype.of(BitChromosome.of(10, 0.5)) 12 13 // 3.) Create the execution environment. 14 val engine = Engine.builder({ gf: Genotype<BitGene> -> eval(gf) }, gtf) 15 16 // 4.) Start the execution (evolution) and collect the result. 17 val result = engine.stream() 18 .limit(100) 19 .collect(EvolutionResult.toBestGenotype()) 20 21 println("Hello World:\n$result") 22 23}
「3.」のEngine.builder の部分でコンパイルエラーとなっています。
エラーは以下の通りです。
呼び出し先のメソッドの定義は以下の通りです。
Java
1public static <G extends Gene<?, G>, C extends Comparable<? super C>> Engine.Builder<G, C> builder(Function<? super Genotype<G>, ? extends C> ff, Factory<Genotype<G>> genotypeFactory) { 2 return new Engine.Builder(genotypeFactory, ff); 3}
ラムダ式 { gf: Genotype<BitGene> -> eval(gf) } の型は (Genotype<BitGene>) -> Int) です。
JavaとKotlinのジェネリクス変性について私が理解できていないか、理解が誤っていることが原因だと思うのですが、何が問題でどう記述するのが正しいかがわかりません。
ちょっと複雑なので混乱しているだけかもしれません。
ご教示いただければと思います。
Kotlin: 1.2.31
Java: 1.8.0_152-release-1136-b27 amd64
IntelliJ IDEA 2018.1.1 (Ultimate Edition) Build #IU-181.4445.78
Windows10
###■追記1
「3.」の部分を以下のように書き換えたところ、コンパイルは通ったのですが、実行時に以下のエラーとなってしまいました。
Kotlin
1val engine = Engine.builder(java.util.function.Function { gf: Genotype<BitGene> -> eval(gf) }, gtf).build()
Error:Kotlin: [Internal Error] org.jetbrains.kotlin.codegen.CompilationException: Back-end (JVM) Internal error: Error type encountered: (???..???) (FlexibleTypeImpl). Cause: Error type encountered: (???..???) (FlexibleTypeImpl). File being compiled at position: (26,3) in C:/Users/mosa/Documents/hoge/src/main/java/HelloWorld.kt The root cause was thrown at: KotlinTypeMapper.java:122 at org.jetbrains.kotlin.codegen.ExpressionCodegen.genQualified(ExpressionCodegen.java:328) at org.jetbrains.kotlin.codegen.ExpressionCodegen.genStatement(ExpressionCodegen.java:372) at org.jetbrains.kotlin.codegen.ExpressionCodegen.generateBlock(ExpressionCodegen.java:1193) at org.jetbrains.kotlin.codegen.ExpressionCodegen.generateBlock(ExpressionCodegen.java:1138) at org.jetbrains.kotlin.codegen.CodegenStatementVisitor.visitBlockExpression(CodegenStatementVisitor.java:56) at org.jetbrains.kotlin.codegen.CodegenStatementVisitor.visitBlockExpression(CodegenStatementVisitor.java:22) at org.jetbrains.kotlin.psi.KtBlockExpression.accept(KtBlockExpression.java:44) at org.jetbrains.kotlin.codegen.ExpressionCodegen.genQualified(ExpressionCodegen.java:307) at org.jetbrains.kotlin.codegen.ExpressionCodegen.genStatement(ExpressionCodegen.java:372) at org.jetbrains.kotlin.codegen.ExpressionCodegen.gen(ExpressionCodegen.java:338) at org.jetbrains.kotlin.codegen.ExpressionCodegen.returnExpression(ExpressionCodegen.java:1590) ・ ・ ・
###■追記2
「3.」の部分を以下のように書き換えたところ、追記1と同じ現象になってしましました。
Kotlin
1 val func: java.util.function.Function<Genotype<BitGene>, Int> = java.util.function.Function { gf: Genotype<BitGene> -> eval(gf) } 2 val engine = Engine.builder(func, gtf).build()
###■追記3
元の問題についてはだいぶわかりました。変性は関係ありませんでした。
当たり前なのかもしれませんが、 Java の Function を引数にとるメソッドに Kotlin のラムダ式を渡そうとしても型が違うのでコンパイルが通らない、ということを理解していませんでした。
Kotlin
1// これの型は (Genotype<BitGene>) -> Int 2val hoge = { gf: Genotype<BitGene> -> eval(gf) } 3 4// これの型は java.util.function.Function<Genotype<GitGene>, Int> 5val piyo = java.util.function.Function { gf: Genotype<BitGene> -> eval(gf) }
###■追記4
KSwordOfHasteさんに教えていただいた結果、動作するようにできました。
ご指摘のとおり、kotlinのコンパイラのバグのようです。
Collectorのメソッド型引数を明示的にすることで CompilationException 発生しなくなりました。
Kotlin
1// 2.) Definition of the fitness function. 2fun eval(gt: Genotype<BitGene>): Int { 3 return gt.chromosome 4 .`as`(BitChromosome::class.java) 5 .bitCount() 6} 7 8fun main(vararg args: String) { 9 10 // 1.) Define the genotype (factory) suitable for the problem. 11 val gtf = Genotype.of(BitChromosome.of(10, 0.5)) 12 13 // 3.) Create the execution environment. 14 val engine = Engine.builder(java.util.function.Function<Genotype<BitGene>, Int> { eval(it) }, gtf).build() 15 16 // 4.) Start the execution (evolution) and collect the result. 17 val result = engine.stream() 18 .limit(100) 19 .collect(EvolutionResult.toBestGenotype<BitGene, Int>()) 20 21 println("Hello World:\n$result") 22 23}
ちなみに結果は以下のようになり、遺伝的アルゴリズムにより10個体100世代で10bitのうち最もビットが立つものを探索する、というものでした。
Hello World: [00000011|11111111]
ありがとうございました。
回答1件
あなたの回答
tips
プレビュー