Error de compilation llamando a un método de extensión desde otro método de extensión en Kotlin

Cuando trato de llamar a un método de extensión desde otro método de extensión (sobrecargando ese método) no se comstack en IntelliJ 14.1.5 y Kotlin 0.14.449

Como soy nuevo en el lenguaje y en la reference, no se prohíbe hacerlo; me gustaría saber:

  • ¿Es posible llamar a un método de extensión desde otro método de extensión?
  • ¿La syntax que uso es correcta (y, por lo tanto, es un error)?
  • Si no, ¿cuál es la syntax correcta?

Este es el código que no comstack:

fun String.replace (prefix: String, suffix: String, vararg parameters: Pair<String, String>) = parameters.fold(this, { result, pair -> result.replace (prefix + pair.first + suffix, pair.second) }) fun String.replace (vararg parameters: Pair<String, String>) = this.replace ("", "", parameters) 

¡Gracias por adelantado!

Hay otras respuestas, pero aquí hay más notas sobre lo que está sucediendo y una solución similar que mantiene el nombre del método, evita la recursión y mantiene varargs para ambas firmas de methods:

  • Al pasar una varargs a otra, necesita usar el operador de propagación porque las varargs se reciben como una matriz, quiere convertirlas nuevamente en una list de parameters y el operador de propagación lo hace.

  • La llamada dentro de fold() lambda accidentalmente se llama a sí misma. Como llama a string.replace() con 2 parameters, ¿qué versión gana? La versión string.replace(String, String, vararg Pair<String,String>) o string.replace(String, String, Boolean[defaulted to false]) ? Ambos se ven iguales cuando solo se llama con 2 parameters. Y el local gana y, por lo tanto, tiene recursion. Para forzar una llamada a la function de sustitución stdlib, el 3er parámetro se convierte en false por defecto, así que pase ese valor específicamente para que se encuentre la firma correcta del método.

Código de trabajo:

 fun String.replace(prefix: String, suffix: String, vararg parameters: Pair<String, String>) { parameters.fold(this) { result, pair -> // add a last parameter to differentiate what version I want called, the one with optional // boolean parameter last (ignoreCase: Boolean = false). Otherwise this recurses on accident. result.replace(prefix + pair.first + suffix, pair.second, false) } } fun String.replace(vararg parameters: Pair<String, String>) { this.replace ("", "", *parameters) // add * spread operator } 

Su problema es que el primer String.replace se llama recursivamente y nunca se alcanza el String.replace principal. Además, el vararg en el segundo pasa al primero como una matriz> por lo que llamar a la segunda function nunca coincidirá con la primera.

 fun String.replace(vararg parameters: Pair<String, String>) = this.replace("", "", parameters) fun String.replace(prefix: String, suffix: String, parameters: Array<out Pair<String, String>>) = parameters.fold(this, { result, pair -> result.replace(prefix + pair.first + suffix, pair.second) }) 

Como pensé que era un error, busqué en el rastreador de problemas de Kotlin y encontré esto: https://youtrack.jetbrains.com/issue/KT-2079

La syntax correcta para pasar un argumento vararg a otra function está usando un asterisco '*':

 fun String.filter (prefix: String, suffix: String, vararg parameters: Pair<String, String>) = parameters.fold(this, { result, pair -> result.replace (prefix + pair.first + suffix, pair.second) }) fun String.filter (vararg parameters: Pair<String, String>) = this.filter("", "", *parameters) 
  • Error de time de ejecución de Kotlin SAM: NoSuchMethodError: no hay método estático
  • ¿Cómo obtengo un número fijo de celdas de cambio de tamaño sin relleno en javafx?
  • ¿Hay alguna manera de hacer que scroll de ViewPager DecorView tenga el contenido del fragment?
  • Botón Kotlin / Anko enHaga clic en no funcionar
  • ¿Kotlin tiene una function de identidad?
  • Iteración de files, split por patrón
  • tornadofx EventBus expande la fila de la tabla usando el object tableview
  • Uso de elementos HTML estándar en KotlinJS escritos de forma segura
  • Corutinas paralelas de Kotlin
  • Firebase Realtime Database, ¿cómo saber el estado de "synchronization"?
  • Rx Java Retrofit con flatMap se ejecuta solo una vez