When we invoke a function that has some parameters, we can pass arguments by the names of these parameters. This approach can improve the readability of your code, especially if a function has lots of parameters. Also, it is a convenient way to change the order of arguments passed in a function call.
Improving code readability
Imagine a cashier who sells cinema tickets, and the ticket price remains the same over the course of a day. You need to calculate how much money our cashier will have at the end of the workday. We can do it with a function that has three parameters:
fun calcEndDayAmount(startAmount: Int, ticketPrice: Int, soldTickets: Int) =
startAmount + ticketPrice * soldTickets
startAmountis an initial sum in the cash desk.ticketPriceis the price of a ticket.soldTicketsis the number of tickets sold on this day.
It is a regular function, so we can invoke it like this:
val amount = calcEndDayAmount(1000, 10, 500) // 6000
This would work fine, although there is one problem: unclear arguments. Of course, we can declare standard variables and pass them on, but sometimes you have to work with literals, not variables. Named arguments can make our code more readable. To fix this problem, you can name each argument of this function:
val amount = calcEndDayAmount(
startAmount = 1000,
ticketPrice = 10,
soldTickets = 500
) // 6000
Now, the code is easy to understand!
Reordering arguments
You can change the order of arguments in a function call with the help of named arguments. All you need to do is to specify the names in any order you want:
val amount = calcEndDayAmount(
ticketPrice = 10,
soldTickets = 500,
startAmount = 1000
) // 6000Named and positional arguments
You can also call a function with named and regular (positional) arguments, as long as named arguments are placed after positional ones:
calcEndDayAmount(1000, ticketPrice = 10, soldTickets = 500) // 6000
Kotlin 1.4 or later allows you to use positional arguments after named arguments, but you need to maintain their order. For example:
calcEndDayAmount(ticketPrice = 10, 500, 1000) // Incorrect invocation!
calcEndDayAmount(startAmount = 1000, 10, 500) // OK
calcEndDayAmount(soldTickets = 500, ticketPrice = 10, startAmount = 500) // OK
calcEndDayAmount(soldTickets = 500, ticketPrice = 10, 500) // Incorrect invocation!Default and named arguments
You can also use named and default arguments together. As you probably know, default arguments are sometimes confusing as Kotlin may not understand which parameters to assign.
Let's modify the previous function and make the first parameter optional:
fun calcEndDayAmount(startAmount: Int = 0, ticketPrice: Int, soldTickets: Int) =
startAmount + ticketPrice * soldTickets
Suppose we would like to invoke this function with only two last parameters. But it won't work:
val amount = calcEndDayAmount(10, 500) // Won't work —
// no value for soldTickets
Here 10 is assigned to the first optional argument startAmount, not to the second parameter ticketPrice.
To invoke this function, use named arguments:
val amount = calcEndDayAmount(ticketPrice = 10, soldTickets = 500) // 5000
Now it works!
Named arguments and default values
The default values for function parameters may or may not be constant. They can also be another named argument or a function.
For example:
fun sum2(a: Int, b: Int = a) = a + b
sum2(1) // 1 + 1
sum2(2, 3) // 2 + 3
The following code won't work, since the b parameter is not initialized:
fun sum2(a: Int = b, b: Int) = a + bConclusion
To sum it all up, use named arguments wisely to improve code readability and change the argument order when some parameters have default values.