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

  • ¿Cómo pasar arguments a la function lambda anónima en Kotlin?
  • Configuración de oyentes de Android en Kotlin: uso del retorno en lambdas
  • Comparador como lambda
  • Usar interfaces funcionales con types de funciones en Kotlin
  • ¿Cuál es el propósito de Lambda's con Receiver?
  • ¿Por qué Kotlin no puede inferir el siguiente argumento lambda (después de la conversión de Java -> Kotlin)?
  • Kotlin: function genérica como tipo de retorno?
  • Kotlin: ambigüedad de resolución de sobrecarga lambda y sobrecarga
  • Reescriba el código de Java en Kotlin utilizando la reference de function.
  • Obtuvo NoClassDefFoundError al pasar el map de lambda
  • Poniendo un lambda genérico en un map