ProgrammatieKotlin ontwikkelaar

Hoe worden hogere-ordefuncties en lambda-expressies in Kotlin geïmplementeerd? Beschrijf de nuances van het doorgeven en retourneren van functies, syntaxiskenmerken, belangrijke beperkingen en geef codevoorbeelden.

Slaag voor sollicitatiegesprekken met de Hintsage AI-assistent

Antwoord.

Hogere-ordefuncties zijn functies die andere functies als parameters accepteren of deze retourneren. Kotlin gebruikt lambda-expressies om gedrag eenvoudig als waarde door te geven.

Voorbeeld van declaratie:

fun operateOnNumbers(a: Int, b: Int, operation: (Int, Int) -> Int): Int { return operation(a, b) } val sum = operateOnNumbers(3, 2) { x, y -> x + y } // sum = 5

Doorgeven van functies:

  • Functies kunnen niet alleen als lambda-expressie worden doorgegeven, maar ook als een verwijzing: :
fun multiply(x: Int, y: Int) = x * y operateOnNumbers(2, 3, ::multiply)

Retournieren van een functie:

fun makeMultiplier(factor: Int): (Int) -> Int = { x -> x * factor } val triple = makeMultiplier(3) val result = triple(10) // 30

Kenmerken:

  • Een lambda kan niet meer dan één niet-genaamd parameter hebben (it).
  • Genummerde parameters kunnen aan de functie worden doorgegeven, maar types moeten expliciet worden opgegeven als het type niet kan worden afgeleid.
  • Lambda-expressies zijn objecten (anonieme klassen), wat de prestaties kan beïnvloeden bij een groot aantal aanroepen in hete lussen (dit wordt opgelost met inline-functies).
  • Voor lambda's die variabelen vastleggen, wordt een closure gebruikt.

Valstrikvraag.

Wat is het verschil tussen de functie-aanduiding (Int, Int) -> Int en het gebruik van het type Function2<Int, Int, Int>?

Antwoord: De syntaxis (Int, Int) -> Int is gewoon een "mooie" aanduiding (syntactische suiker) voor het Function2<Int, Int, Int>-interface. In de praktijk zijn beide varianten volledig uitwisselbaar.

val f1: (Int, Int) -> Int = { x, y -> x + y } val f2: Function2<Int, Int, Int> = { x, y -> x + y }

Maar de eerste variant is meestal te verkiezen vanwege de leesbaarheid.

Voorbeelden van echte fouten door onbekendheid met de nuances van het onderwerp.


Verhaal

In een grootschalig evenementenverwerkingssysteem werden tientallen lambda-expressies binnen een lus gemaakt zonder het gebruik van inline-functies. Dit veroorzaakte een hoge belasting voor de GC en een verslechtering van de prestaties, omdat voor elke aanroep een afzonderlijk anoniem functie-object werd gemaakt.


Verhaal

Bij het proberen terug te keren uit een andere functie was de handtekening van de geretourneerde functie niet correct opgegeven, wat leidde tot een compilatiefout en een lange zoektocht naar de oorzaak. De fout was dat er geen haakjes in het type stonden: fun foo(): Int -> Int in plaats van het juiste fun foo(): (Int) -> Int.


Verhaal

Een ontwikkelaar probeerde een lambda zonder expliciete type-aanduiding te gebruiken als parameter voor een andere functie met een niet-expliciet afgeleid type, wat leidde tot de fout "cannot infer a type for this parameter". Het probleem werd opgelost door expliciet het type van de lambda of parameters van de functie op te geven.