¿Cómo puedo hacer que kotlin se dé count de que esta function de comparación de BST es recursiva de queue?

Aquí hay una class simple de tree de búsqueda binaria que reuní.

data class Bst<T: Comparable<T>>(var left: Bst<T>?, var value: T, var right: Bst<T>?) { tailrec fun contains(key: T): Boolean { return if (key < value) { left?.contains(key) ?: false } else if (key > value) { right?.contains(key) ?: false } else { true } } } 

Desafortunadamente, cuando pego esto en try.kotlinlang.org , dice que las llamadas recursivas no son recursivas de queue. Si refactorizo ​​el código de la left?.contains en una instrucción if que testing para left == null , aparece otro error sobre cómo left es mutable y podría haber cambiado desde la instrucción if . ¿Cómo puedo hacer que estas llamadas sean recurrentes a los ojos de kotlin?

Como se indica en las funciones recursivas de Tail :

Para ser elegible para el modificador de tailrec , una function debe llamarse a sí misma como la última operación que realiza. No puede usar recursion final cuando hay más código después de la llamada recursiva, y no puede usarlo en los bloques try / catch / finally.

Allí su implementación ya falla con la primera restricción para llamar a la function de nuevo. Aunque llame a esta function, es en otra instancia y tampoco en la última operación de este bloque.

Lo mejor que se me ocurrió fue implementarlo "estáticamente" en el context de Kotlin .

 data class Bst<T: Comparable<T>>(var left: Bst<T>?, var value: T, var right: Bst<T>?) { fun contains(key: T) = contains(key, this) companion object { tailrec fun <T: Comparable<T>> contains(key: T, bst: Bst<T>): Boolean { if (key == bst.value) return true val bst2 = bst.run { if (key < value) left else right } if (bst2 == null) return false return contains(key, bst2) } } } 

Pero, además, debe considerar implementar un patrón de valor nulo, en lugar de usar valores que aceptan valores nulos para la izquierda y la derecha. Puede utilizar classs selladas para esto.

  • Devuelve el índice doble del elemento de la colección mientras itera
  • ¿Cómo crear funciones a nivel de package?
  • ¿Cómo puedo inicializar la variable antes de cada testing usando el marco kotlin-test
  • Moshi / Kotlin - ¿Cómo serializar cadenas NULL JSON en cadenas vacías?
  • Kotlin sincronizado
  • La barra de estado no es transparente, pero es blanca
  • Bloqueando el serialVersionUID en Kotlin
  • Agregar list de subtypes a la list de supertypes en Kotlin
  • ¿Android Studio 3.0 agrega información de request de parameters?
  • No se puede resolver el símbolo @ReadOnly y @Mutable en la compilation de Kotlin 1.1.0
  • Proguard: no ofusque las classs de datos de Kotlin