0
0
Kotlinprogramming~15 mins

Infix functions for readable calls in Kotlin - Deep Dive

Choose your learning style9 modes available
Overview - Infix functions for readable calls
What is it?
Infix functions in Kotlin let you call functions in a way that looks like natural language. Instead of using the usual dot and parentheses, you write the function name between the object and its argument. This makes code easier to read and write, especially for simple operations. Infix functions must be member functions or extension functions with a single parameter.
Why it matters
Without infix functions, code can look cluttered with dots and parentheses, making it harder to understand at a glance. Infix functions improve readability and expressiveness, helping developers write code that feels like plain English. This reduces mistakes and makes collaboration smoother, especially in complex projects.
Where it fits
Before learning infix functions, you should understand basic Kotlin functions, member functions, and extension functions. After mastering infix functions, you can explore operator overloading and DSL (Domain Specific Language) creation in Kotlin, which also focus on making code more readable and expressive.
Mental Model
Core Idea
Infix functions let you write function calls like simple phrases, making code read like natural language.
Think of it like...
It's like using a shortcut phrase in conversation instead of a full sentence, for example saying 'give me' instead of 'please give me the item'.
Object ── infixFunction ──> Argument

Example:
Alice greet Bob
means
Alice.greet(Bob)
Build-Up - 7 Steps
1
FoundationBasic function call syntax in Kotlin
🤔
Concept: Understanding how normal function calls work in Kotlin is essential before learning infix functions.
In Kotlin, you call a function on an object using dot notation and parentheses. For example: val result = 5.plus(3) This calls the 'plus' function on the number 5 with 3 as an argument.
Result
The output of 5.plus(3) is 8.
Knowing the standard function call format helps you appreciate how infix functions simplify and improve readability.
2
FoundationMember and extension functions basics
🤔
Concept: Functions can be part of a class (member functions) or added to existing classes (extension functions).
Member function example: class Person { fun greet(name: String) = "Hello, $name" } Extension function example: fun Int.timesTwo() = this * 2 These functions can be called normally with dot and parentheses.
Result
Calling Person().greet("Alice") returns "Hello, Alice". Calling 4.timesTwo() returns 8.
Understanding these function types is key because infix functions must be either member or extension functions.
3
IntermediateDefining an infix function
🤔Before reading on: do you think any function can be infix, or are there restrictions? Commit to your answer.
Concept: Infix functions are special functions marked with the 'infix' keyword and must have exactly one parameter.
To define an infix function, add the 'infix' keyword before 'fun'. For example: class Person { infix fun greet(name: String) = "Hello, $name" } Now you can call it as: Person() greet "Alice"
Result
The call Person() greet "Alice" returns "Hello, Alice" without using dot or parentheses.
Knowing the syntax and restrictions of infix functions helps you write cleaner, more readable code.
4
IntermediateCalling infix functions for readability
🤔Before reading on: do you think infix calls can be chained like normal calls? Commit to your answer.
Concept: Infix functions can be called without dots and parentheses, making code look like natural language. They can also be chained if the return type supports it.
Example: class Person(val name: String) { infix fun likes(other: Person) = "${this.name} likes ${other.name}" } val alice = Person("Alice") val bob = Person("Bob") println(alice likes bob) You can chain if the return type allows: infix fun String.shout(times: Int) = this.repeat(times) println("Hi" shout 3) // HiHiHi
Result
Output: Alice likes Bob HiHiHi
Understanding how infix calls improve readability and can chain helps you write expressive Kotlin code.
5
IntermediateRestrictions and best practices for infix functions
🤔
Concept: Infix functions must be member or extension functions with one parameter and cannot have default or vararg parameters.
You cannot define an infix function with zero or multiple parameters. Also, infix functions should be used for operations that read naturally, like 'to', 'plus', or 'on'. Avoid using infix for complex logic to keep code clear.
Result
Trying to define 'infix fun add(a: Int, b: Int)' will cause a compiler error.
Knowing these rules prevents common mistakes and keeps your code readable and idiomatic.
6
AdvancedUsing infix functions in DSLs
🤔Before reading on: do you think infix functions can help create mini-languages inside Kotlin? Commit to your answer.
Concept: Infix functions are a powerful tool to build Domain Specific Languages (DSLs) that look like natural language or configuration files.
Example DSL snippet: class Robot { infix fun moves(direction: String) = "Robot moves $direction" } val robot = Robot() println(robot moves "forward") This style lets you write code that reads like instructions, improving clarity in complex setups.
Result
Output: Robot moves forward
Understanding infix functions' role in DSLs shows their power beyond simple syntax sugar.
7
ExpertCompiler handling and performance of infix calls
🤔Before reading on: do you think infix calls are slower than normal calls? Commit to your answer.
Concept: Infix calls are just syntactic sugar; the Kotlin compiler translates them into normal function calls with no runtime overhead.
The compiler converts: alice likes bob into alice.likes(bob) This means infix functions have the same performance as regular calls. They do not create extra objects or slow down execution.
Result
Infix calls run as fast as normal calls with no difference in bytecode.
Knowing infix functions are optimized away helps you use them freely without worrying about performance.
Under the Hood
Infix functions are compiled by Kotlin into normal function calls. The 'infix' keyword only changes how you write the call in source code, not how it runs. The compiler checks that the function is a member or extension with one parameter and then rewrites the infix call into a standard call with dot and parentheses during compilation.
Why designed this way?
The design aims to improve code readability without adding runtime cost or complexity. By restricting infix functions to one parameter and member/extension functions, Kotlin keeps the syntax simple and unambiguous. This avoids parsing difficulties and maintains backward compatibility with existing function call syntax.
Source code with infix call
  │
  ▼
Kotlin compiler parses infix keyword and call
  │
  ▼
Validates function signature (one parameter, member/extension)
  │
  ▼
Transforms infix call into normal call
  │
  ▼
Generates bytecode for normal function call
  │
  ▼
Runs with no runtime difference
Myth Busters - 4 Common Misconceptions
Quick: Do infix functions allow multiple parameters? Commit to yes or no.
Common Belief:Infix functions can take multiple parameters like normal functions.
Tap to reveal reality
Reality:Infix functions must have exactly one parameter; multiple parameters are not allowed.
Why it matters:Trying to use multiple parameters causes compiler errors and confusion about how to write calls.
Quick: Are infix functions slower than normal function calls? Commit to yes or no.
Common Belief:Infix functions add overhead and slow down the program.
Tap to reveal reality
Reality:Infix functions compile down to normal calls with no extra runtime cost.
Why it matters:Avoiding infix functions due to performance fears limits code readability unnecessarily.
Quick: Can any function be called using infix syntax without declaration? Commit to yes or no.
Common Belief:Any function can be called using infix syntax even if not declared infix.
Tap to reveal reality
Reality:Only functions declared with the 'infix' keyword can be called using infix syntax.
Why it matters:Trying to call non-infix functions infix causes syntax errors and confusion.
Quick: Do infix functions always improve readability? Commit to yes or no.
Common Belief:Using infix functions always makes code easier to read.
Tap to reveal reality
Reality:Infix functions improve readability only when used for simple, natural operations; overusing them can make code confusing.
Why it matters:Misusing infix functions can reduce code clarity and maintainability.
Expert Zone
1
Infix functions cannot be overridden with different parameter counts, preserving call consistency.
2
When chaining infix calls, the return type must support further calls or the chain ends, which affects DSL design.
3
Infix functions can be combined with operator overloading for very expressive APIs, but this can confuse readers if overdone.
When NOT to use
Avoid infix functions for operations that require multiple parameters, complex logic, or when the call does not read naturally. Use normal function calls or named parameters instead. For complex DSLs, consider using builder patterns or lambda with receivers for clearer structure.
Production Patterns
Infix functions are widely used in Kotlin libraries for creating readable APIs, such as 'to' for pairs, 'downTo' for ranges, and in testing frameworks for assertions. They help create fluent interfaces and mini-languages that improve developer experience.
Connections
Operator overloading
Builds-on
Both infix functions and operator overloading aim to make code more natural and expressive by changing how functions are called or operators behave.
Domain Specific Languages (DSLs)
Same pattern
Infix functions are a key tool in building DSLs that read like natural language, improving clarity and reducing boilerplate.
Natural language processing (NLP)
Analogous pattern
Just as NLP tries to make computers understand human language, infix functions let programmers write code that looks more like human language, bridging the gap between logic and expression.
Common Pitfalls
#1Trying to define an infix function with two parameters.
Wrong approach:infix fun add(a: Int, b: Int) = a + b
Correct approach:infix fun add(a: Int) = this + a
Root cause:Misunderstanding that infix functions must have exactly one parameter.
#2Calling a function infix without declaring it infix.
Wrong approach:val result = 5 plus 3 // 'plus' not declared infix
Correct approach:infix fun Int.plus(other: Int) = this + other val result = 5 plus 3
Root cause:Confusing infix call syntax with normal function calls.
#3Using infix functions for complex logic making code hard to read.
Wrong approach:infix fun Person.complexAction(data: Data) { /* many steps */ } person complexAction data
Correct approach:fun Person.complexAction(data: Data) { /* many steps */ } person.complexAction(data)
Root cause:Overusing infix functions beyond simple, natural operations.
Key Takeaways
Infix functions let you call functions in a natural, readable way without dots or parentheses.
They must be member or extension functions with exactly one parameter and marked with the 'infix' keyword.
Infix calls are just syntax sugar and compile to normal function calls with no performance cost.
Using infix functions wisely improves code clarity, especially in DSLs and fluent APIs.
Misusing infix functions for complex logic or multiple parameters leads to errors and confusion.