infix în Kotlin

Funcții și lambda Kotlin 1.0

infix permite apelarea unei funcții cu un parametru fără punct și paranteze: a to b în loc de a.to(b).

Sintaxă
infix fun Tip.nume(param: Tip): Rezultat { ... }

a nume b          // la fel ca a.nume(b)

Ce face infix

O funcție marcată cu infix poate fi apelată ca un operator, între cele două valori: "Ana" to 10 este același lucru cu "Ana".to(10). Biblioteca standard are multe astfel de funcții: to (creează un Pair), until, downTo, step, and, or, xor, shl.

Condiții: funcția trebuie să fie metodă a unei clase sau funcție de extensie, să aibă exact un parametru, fără vararg și fără valoare implicită. Apelul infix are prioritate mai mică decât operatorii aritmetici: 1 + 2 to 3 înseamnă (1 + 2) to 3.

Exemple

Exemplul 1: Funcții infix din biblioteca standard

to creează perechi pentru mapOf. until și step construiesc intervale. and și shl lucrează pe biți.

fun main() {
    val varste = mapOf("Ana" to 21, "Mihai" to 19)
    println(varste)

    val pereche = "Iași" to 290_000
    println("${pereche.first} are ${pereche.second} locuitori")

    for (i in 0 until 10 step 3) print("$i ")
    println()

    println(12 and 10)
    println(1 shl 4)
}

Rezultat

{Ana=21, Mihai=19}
Iași are 290000 locuitori
0 3 6 9 
8
16

Exemplul 2: Funcție infix proprie

ori este o extensie infix pe String. imparteLa împarte o sumă la un număr de persoane.

infix fun String.ori(n: Int): String = this.repeat(n)

infix fun Double.imparteLa(persoane: Int): Double = this / persoane

fun main() {
    println("ha" ori 3)
    println("-" ori 20)
    val notaPlata = 240.0
    println("Fiecare plătește ${notaPlata imparteLa 4} lei")
}

Rezultat

hahaha
--------------------
Fiecare plătește 60.0 lei

Exemplul 3: Metodă infix într-o clasă

Metoda adauga se apelează fără punct. Codul arată ca o propoziție.

class Cos {
    private val produse = mutableListOf<String>()
    infix fun adauga(produs: String) { produse.add(produs) }
    override fun toString() = "Coș: ${produse.joinToString()}"
}

fun main() {
    val cos = Cos()
    cos adauga "pâine"
    cos adauga "lapte"
    cos adauga "mere"
    println(cos)
}

Rezultat

Coș: pâine, lapte, mere

Greșeli frecvente

  • Funcție infix la nivelul de sus, fără receptor (infix fun f(a: Int, b: Int)): nu este permis, trebuie să fie metodă sau extensie cu un singur parametru.
  • Uitarea priorității: x + 1 until 10 se calculează ca (x + 1) until 10. Folosește paranteze când nu ești sigur.
  • Abuzul de infix: folosește-l doar când apelul se citește natural (a to b), altfel codul devine greu de urmărit.

Comenzi înrudite

  • Funcții de extensie: O funcție de extensie adaugă o metodă nouă unui tip existent (String, Int, List), fără să modifici clasa.
  • operator: operator marchează o funcție cu nume special (plus, get, contains, compareTo…) ca să poată fi folosită prin +, [], in sau <.
  • Range-uri (.., ..<, until, downTo, step): Intervale de numere sau caractere: .. include capătul, ..< și until îl exclud, downTo numără invers, step sare.
  • Pair: O pereche de două valori, first și second; a to b este felul scurt de a crea un Pair, folosit în mapOf.