What is an infix function in Kotlin, and what are the rules for declaring one? Use it to explain how `1 to "a"` works.
answer
- infix keyword + single param, no default, no vararg
- member or extension only
- a foo b == a.foo(b)
- to returns Pair, powers mapOf
- left-associative, looser than arithmetic
basics
~20 sAn infix function lets you call it without a dot or parentheses, like 1 to "a". You mark it with the infix keyword. It must be a member or extension function with exactly one parameter and no default value.
solid answer
~40 sAn `infix` function can be called between two operands without `.` or parentheses: `a foo b` means `a.foo(b)`. To qualify it must (1) be marked `infix`, (2) be a member function or an extension function, (3) take exactly one parameter, and (4) that parameter must not be `vararg` or have a default value. `1 to "a"` calls the standard-library `public infix fun <A, B> A.to(that: B): Pair<A, B>`, returning `Pair(1, "a")` — that is how `mapOf(1 to "a")` builds entries. Infix calls have lower precedence than arithmetic but higher than comparison/equality, and you cannot chain them without parentheses ambiguity rules. Infix is the backbone of readable DSLs because it removes punctuation noise.
code
kotlin · 7 linesinfix fun Int.to(that: String): Pair<Int, String> = Pair(this, that)
val m = mapOf(1 to "a", 2 to "b")
println(m) // {1=a, 2=b}
// Desugared form:
val p = 1.to("a") // Pair(1, "a")go deeper
Knows the infix keyword, that it drops the dot/parentheses, and that to builds a Pair.
States all four declaration rules and that it desugars to a normal method call.
Discusses precedence/associativity and when infix helps vs. hurts readability and IDE discoverability.
Frames infix as a DSL-design tool, weighing call-site clarity, API discoverability, and maintenance cost across a team.
## What `infix` is An **infix function** is called *between* its receiver and its single argument, with no dot and no parentheses. Syntactically `a foo b` is exactly `a.foo(b)`. ## Declaration rules A function qualifies as infix only if **all** of these hold: - It is marked with the `infix` keyword. - It is a **member function** (declared inside a class) or an **extension function** (declared on a receiver type). - It has **exactly one** parameter. - That parameter is **not** `vararg` and has **no default value**. ```kotlin infix fun Int.shouldBe(expected: Int) { require(this == expected) { "expected $expected but was $this" } } 3 shouldBe 3 // reads like English; same as (3).shouldBe(3) ``` ## How `1 to "a"` works The Kotlin standard library defines: ```kotlin public infix fun <A, B> A.to(that: B): Pair<A, B> = Pair(this, that) ``` So `1 to "a"` is `1.to("a")`, which produces `Pair(1, "a")`. This is why `mapOf(1 to "a", 2 to "b")` reads naturally — `mapOf` takes `vararg pairs: Pair<K, V>`. ## Precedence and chaining - Infix calls bind **looser** than arithmetic operators (`+`, `*`) but **tighter** than named comparisons and the boolean operators. - `a infix1 b infix2 c` is **left-associative**: `(a infix1 b) infix2 c`. - You must use explicit parentheses when mixing infix with other operators if intent is unclear; e.g. `1 to 2 + 3` parses as `1 to (2 + 3)`. ## When to use it Use `infix` for **binary, symmetric-reading** operations (`to`, `and`, `until`, `step`, `shouldBe`). Avoid it for ordinary calls where a dot is clearer — overusing infix hurts readability and IDE discoverability.
- Can a top-level function (no receiver) be infix?No. Infix requires a receiver, so it must be a member or an extension function — there is no left operand otherwise.
- Why can't an infix function take a vararg or a default-valued parameter?Infix syntax provides exactly one explicit argument with no parentheses, so varargs and defaults would be unrepresentable/ambiguous; the compiler forbids them.
Infix is like saying 'two plus three' out loud instead of 'plus(two, three)' — the operator sits between the words.
saying these in an interview costs you the question
- Claiming infix functions can take two or more parameters
- Saying top-level non-extension functions can be infix
- Thinking `to` is a language keyword rather than a stdlib extension function
- Believing infix changes evaluation order beyond standard left-associativity
- Confusing infix (any single-arg method) with operator overloading (fixed symbol set)