Kotlin funcional. En nombre de la bondad, el arco iris y todo eso

Introducción

Kotlin en sí es una herramienta muy poderosa, pero muchas veces no la usan en toda su capacidad, convirtiéndola en una especie de ... Java 6. Trataré de decirte por qué no deberías hacer esto y cómo usarlo. las características funcionales del lenguaje al máximo.





Funciones de orden superior

Empezaré por ellos. Y, al mismo tiempo, te diré de qué se trata: cuando una función toma otra función como parámetro o la devuelve, es una función de orden superior. Simple, ¿no es así? ¿Pero cómo lo usas?





El hecho de que las funciones en Kotlin puedan recibir y devolver otras funciones por nosotros debería significar que podemos escribirlas en una variable. Se verá algo como esto:





val foo: () -> Unit = {  }
      
      



Luego, podemos pasarlo usando una sintaxis como:





run(foo)
      
      



Genial, pero ¿y si queremos usar una función que hemos definido de la forma habitual? ¿O aprobar un método en absoluto? Bueno, también existe la posibilidad: un enlace a una función . Así es como podemos comprobar si una cadena está vacía:





str.run(String::isEmpty)
      
      



. , , . , . ? ? "" ?



, , , , - :





val parse: (String) -> List<Int> = { it.split(":").map(String::toInt) }

val (xMin, yMin) = parse(data["from"])
val (xMax, yMax) = parse(data["to"])
      
      



, , , , , .  let



run



with



apply



,  also



. ? , .





inline fun <T, R> T.let(block: (T) -> R): R
inline fun <T> T.also(block: (T) -> Unit): T
      
      



let



also



. , - block(this)



. , " " . , . also



, let



, .





inline fun <R> run(block: () -> R): R
inline fun <T, R> T.run(block: T.() -> R): R
inline fun <T, R> with(receiver: T, block: T.() -> R): R
inline fun <T> T.apply(block: T.() -> Unit): T
      
      



run



, with



apply



:

run



let



, apply also



, with



run



, receiver



. , let



also



? , it



this



, .



? .



, , , , , , . "" .





inline



? , , . , , , , .



. .





, , - ( )?



, , :





let {
  val some = Some()
  it.run(some::doSome)
}
      
      



:





let(Some::doSome)
      
      



, , ?





, , ? , . , companion object



:





class Some {
  companion object {
    fun doSome(any: Any) = run {}
  }
}
      
      



, .





Factory

:





val other = Other()
val stuff = other.produceStuff()

val some = Some(stuff)
      
      



. , Other Some, .





, :





val some = Some(
  Other().produceStuff()
)
      
      



. , , ... ? , Factory-:





class Some {
  companion object Factory {
    inline fun <T>create(t: T?, f: (T?) -> Stuff) = Some(f(t))
  }
}
      
      



:





val some = Some(Other()) { it.doStuff() }
      
      



Other :





val some = Some.create(Other) { it.create().doStuff() }
      
      



, . ? , . , .





-

, - , . , , . :





fun Some.foo() = run { }
      
      



:





val foo: Some.() -> Unit = {  }
      
      



, - . -. , IntelliJ IDEA , - , .





, -. val



, foo



, . fun



, , .





:





class Some {
  fun Other.someExtention() = run { }
}
      
      



, , "", - .





, . . . , , - Some Other.





, , , - Some::someExtention



. , - .





P.S.

, , . , KFunction.





fun Some.overlay(f: KFunction1<Some, Any>) = f(this)
      
      



En este caso, tengo dos novedades: la primera es que tus gustos son muy específicos, y la segunda es que en este caso, nuestra función de extensión se procesa como una función muy ordinaria, en la que el primer parámetro es una instancia de la clase que se extiende.








All Articles