skip to content

Infix Functions

A single-parameter function marked infix can be called without a dot or parentheses, which is why to, until, and downTo read like language keywords. Interviewers check that you also know infix calls sit at a lower precedence than arithmetic.

part ofKotlinoverview, primer and where to startread it →
on this pageshow

questions

5

What is an infix function in Kotlin, and what are the requirements a function must satisfy to be callable in infix form?

level: juniorimportance: must knowfreq 55%

answer

  1. Marked `infix`, member or extension, exactly one param
  2. No vararg, no default value on the param
  3. Left = receiver, right = argument
  4. Readability sugar only — same as a.name(b)
  5. `to`, `until`, `downTo`, `shl`, `and`

basics

~10 s

An infix function lets you call it between two values without a dot or parentheses, like 1 to 2. It must be marked infix, be a member or extension, and take exactly one parameter.

solid answer

~40 s

An `infix` function can be invoked in the form `a foo b` instead of `a.foo(b)`. To qualify it must: (1) be a member function or an extension function; (2) be marked with the `infix` modifier; (3) accept exactly one parameter; (4) that parameter must not be a `vararg` and must not have a default value. The left operand is the receiver, the right is the argument. Common standard-library examples are `to` (builds a `Pair`), `until`, `downTo`, `step`, `shl`, `shr`, `and`, `or`, and `xor`. Infix exists purely for readability — `map.put(k, v)` versus `mapOf(a to b)` reads more like prose. It changes only call syntax, not semantics; you can always still call it with the normal dot form.

code

kotlin · 8 lines
kotlin
infix fun Int.times2(other: Int): Int = this * other

val a = 6 times2 7   // 42
val b = 6.times2(7)  // 42 — dot form still valid

// stdlib infix examples
val p = "key" to "value"      // Pair("key", "value")
val r = (1 until 5).toList()   // [1, 2, 3, 4]

go deeper

for a junior

States the infix modifier, member-or-extension, exactly-one-param rule, and gives to as an example.

for a middle

Adds the no-vararg / no-default constraint and notes receiver-vs-argument and that the dot form still works.

for a senior

Frames infix as pure readability sugar compiling to a.name(b) and distinguishes it from operator overloading.

for a principal

Discusses when infix improves API ergonomics vs. when it harms clarity, and library design conventions around it.

## What an infix function is An **infix function** is a function you can call by placing its name *between* two operands, with no dot and no parentheses: ```kotlin infix fun Int.shl(bits: Int): Int = this shl bits // (conceptual) val pair = 1 to 2 // instead of 1.to(2) val shifted = 1 shl 4 // instead of 1.shl(4) -> 16 ``` The value on the **left** of the function name is the **receiver** (`this`), the value on the **right** is the single **argument**. ## The four rules A function is eligible for infix calls only if ALL of these hold: - It is a **member function** (declared inside a class/object) **or** an **extension function** (declared as `fun Receiver.name(...)`). Top-level functions with no receiver cannot be infix. - It is marked with the **`infix`** modifier keyword. - It has **exactly one parameter**. - That parameter is **not `vararg`** and has **no default value**. ```kotlin infix fun String.repeated(times: Int): String = this.repeat(times) val s = "ab" repeated 3 // "ababab" val s2 = "ab".repeated(3) // identical — dot form always works ``` ## Why it exists Infix is **syntactic sugar for readability only**. It does not change dispatch, performance, or semantics. The classic motivation is DSL-like, prose-like code: `mapOf("a" to 1, "b" to 2)` reads naturally because `to` is infix. Range builders `1 until 10`, `10 downTo 1`, `1..10 step 2` rely on it too. ## Things that are NOT infix - Operators like `+` use **operator overloading** (the `operator` modifier), a different mechanism. - You still need the receiver and argument to be unambiguous; mixing infix calls with other operators requires understanding precedence (covered separately). Under the hood the compiler simply rewrites `a name b` into `a.name(b)`.

  • Can a top-level function with no receiver be infix?
    No. Infix functions must be a member or an extension, so they always have a receiver as the left operand.
  • Does adding `infix` remove the ability to call with a dot?
    No. `a foo b` and `a.foo(b)` are both valid; `infix` only adds the dot-less form.

Like writing '3 plus 4' in English instead of 'plus(3, 4)' — same operation, more readable word order.

saying these in an interview costs you the question

  • Claiming any function can be infix
  • Saying infix functions can take multiple parameters
  • Confusing infix with operator overloading (`operator` modifier)
  • Thinking infix changes performance or dispatch
  • Allowing a default value or vararg on the infix parameter

context

open as a page

How does the standard-library `to` function work, and how do `until`, `downTo`, and `step` use infix to make range code read naturally?

level: middleimportance: must knowfreq 50%

basics

~20 s

to is an infix extension that builds a Pair, so "a" to 1 makes Pair("a", 1). until, downTo, and step are infix functions that build ranges/progressions, letting you write 0 until n or 10 downTo 1 step 2.

open as a page

Where do infix function calls sit in Kotlin's operator precedence, and how does that affect an expression like `1 + 2 shl 3` or `a == b and c`?

level: middleimportance: should knowfreq 40%

basics

~10 s

Infix calls have lower precedence than arithmetic operators (+, -, *) but higher than comparisons, equality, and the logical &&/||. So arithmetic binds first, then infix, then comparisons.

open as a page

When is it appropriate to add the `infix` modifier to an API, and what are the design pitfalls? Give an example of a well-designed infix function.

level: seniorimportance: should knowfreq 30%

basics

~20 s

Use infix only when the call reads like a natural two-word phrase (x shouldBe y). Avoid it when the operand order is unclear, when there are side effects, or when precedence with other operators could confuse readers.

open as a page

Inside a class, how does an infix member function bind to `this`, and what subtle issue arises when you call an infix member from within the same class without specifying a receiver?

level: seniorimportance: nice to knowfreq 18%

basics

~20 s

An infix member's left operand is its receiver. If you call it inside the class without a left operand, you must write this name arg explicitly — bare name arg doesn't work, because infix needs an explicit left side.

open as a page