auser
auser

Reputation: 7497

Kotlin default parameter ordering

Does anyone know why the call to method1 does not compile whereas the call to method2 does?

class MyApp {

    interface X {

        fun <Q : Any, A : Any> method1(argStr: String = "", argQ: Q, argH: (A) -> Unit)

        fun <Q : Any, A : Any> method2(argQ: Q, argStr: String = "", argH: (A) -> Unit)
    }

    fun test(x: X) {

        /* Call to method1 does not work - the following errors are produced
         * Error: Kotlin: Type inference failed:
         * fun <Q : Any, A : Any> method1(argStr: String = ..., argQ: Q, argH: (A) -> Unit): Unit
         * cannot be applied to (Int,(Int) -> Unit)
         * Error: Kotlin: The integer literal does not conform to the expected type String
         * Error: Kotlin: No value passed for parameter 'argQ'
         */
        
        x.method1(1) { res: Int -> println(res) }

        /* No errors here */
        x.method2(1) { res: Int -> println(res) }
    }

}

Upvotes: 3

Views: 1379

Answers (2)

lmiguelvargasf
lmiguelvargasf

Reputation: 69745

It is possible to place a parameter with a default value before a regular parameter (no default value). However, you have to keep in mind the following:

  1. The value for the regular parameter will be required, so the caller will be forced to always provide a value for the parameter with default argument which makes meaningless the purpose of having a default argument. The following will work:
x.method1("", 1) { res: Int -> println(res) }
  1. The caller may skip the default parameter if they use named arguments. This is the reason the following works:
x.method1(argQ = 1) { res: Int -> println(res) }

It is always a good idea to put parameters with default parameters in trailing positions unless the last parameter stands for a lambda expression.

Upvotes: 1

minhazur
minhazur

Reputation: 4988

If a default parameter precedes a parameter with no default value, the default value can only be used by calling the function with named arguments.

Example:

fun foo(bar: Int = 0, baz: Int) { ... }

foo(baz = 1) // The default value bar = 0 is used

In your example this will work:

x.method1(argQ = 1) { res: Int -> println(res) } // The default value argStr = "" is used

Further reading

Upvotes: 6

Related Questions