Kotlin Cualquiera con lambdas

Si bien el código proporcionado con la pregunta es bastante trivial, la pregunta se centra en el aspecto más general de la security de tipo:

Tengamos una function lambda como esta:

{it: (Any) -> Any -> it(it)} 

Toma otra lambda y la ejecuta consigo misma como parámetro. Así que hagamos lo obvio y llámenlo consigo mismos como parámetro:

 {it: (Any) -> Any -> it(it)}.apply { this.invoke(this) } 

Pero eso no funciona tan bien como pensé: recibo el siguiente error en el momento de la compilation:

Tipo no coincidente: el tipo inferido es ((Cualquiera) -> Cualquiera) -> Cualquiera excepto (Cualquiera) -> Cualquiera se esperaba

De acuerdo. Así que probemos este:

 val lambda: (Any) -> Any = { Unit } 

El valor real de esta propiedad no importa, no estoy interesado en el resultado, solo en el comportamiento del comstackdor. Entonces aquí hay otra propiedad:

  val kappa: (Any) -> Any = lambda 

Ok, ahora esto realmente comstack. ¿Pero no es eso lo mismo que antes? Paso una (Any) -> Any function a una propiedad (en el otro caso es un argumento), que espera una (Any) -> Any function. La lógica me dice: Sí, (Any) -> Any es de tipo Any , porque todo lo es. Pero, ¿por qué eso no funciona con la invocación lambda? De hecho, puedo convertir explícitamente mi lambda en una (Any) -> Any function, lo que dará como resultado un elenco sin marcar, pero se comstackrá y la ejecución da como resultado un StackOverflowError como se esperaba.

 {it: (Any) -> Any -> it(it)}.apply { this.invoke(this as (Any) -> Any) } 

¿Dónde está la diferencia?

De acuerdo, como dije en los comentarios, hay mucha confusión irrelevante en la forma en que se plantea esta pregunta. Comencemos limpiando algo de esto:

 val fn1 = {x1: (Any) -> Any -> x1(x1)} 

El tipo de fn1 es ((Any) -> Any) -> Any . El tipo de x1 es (Any) -> Any . La definición anterior comstack. El comstackdor de Kotlin no tiene problemas para ver que x1 es Any .

El bash de invocar fn1 en sí mismo, sin embargo, no funciona. … y el comstackdor dice exactamente por qué: fn1 es una function que es un ((Any) -> Any) -> Any y no puede usarse como (Any) -> Any . ¿Por qué eso no funciona? Bueno, ¡porque alguien podría invocar el argumento!

Para que sea más fácil discutir, creemos una segunda function, muy similar a la primera:

 val fn2 = {x2: (Any) -> Any -> x2("foo")} 

También comstack, bien. Y ahora toda esta pregunta se networkinguce a:

Por qué esto no funciona: fn2(fn1)

Pero debería ser obvio, en este punto. Si esa llamada funcionó (no importa cuánto apply o invoke engaño) el bash de invocar x2 (dentro de fn2 ) no puede funcionar, porque x2 es un alias para fn1 . Es una llamada a fn1 con el argumento "foo" , donde espera una function.

tl; dr: las funciones son contravariantes en sus types de arguments

  • Función para expresión lambda
  • Funciones de Lambda con comodines en Kotlin
  • ¿Cómo pasar arguments a la function lambda anónima en Kotlin?
  • ¿Por qué la variable no se puede inicializar correctamente en la function en línea como en Java?
  • La expresión lambda no se usa
  • java.lang.NoClassDefFoundError $$ inlined $ forEach $ lambda $ 1 en Kotlin
  • Kotlin: Declaración a Lambda
  • Polimorfismo en las funciones de extensión en Kotlin
  • ¿Cómo mejorar la syntax de kotlin lambda?
  • Comparador como lambda
  • cómo descartar DialogFragment de lambda especificado en el llamador Kotlin