25

Which solution is better? Using a nullable lambda or passing an empty lambda as a default parameter? Would kotlin somehow optimize empty lambda, or create a new instance that does nothing?

class Test1(val action: () -> Unit = {})

Unfortunately, I do not understand generated byte code. Let's analyze

val test11 = Test1()

After decompilation gives us:

private static final Test1 test11 = new Test1((Function0)null, 1, (DefaultConstructorMarker)null);

And finally, as a lambda is passed, something like this:

var1 = (Function0)null.INSTANCE;

Edit: The hidden questions is: How does Kotlin treat an empty lambda as a default value?

ouflak
  • 2,458
  • 10
  • 44
  • 49
Paweł Byszewski
  • 390
  • 1
  • 5
  • 11
  • Which solution is better depends on what you're trying to achieve or optimize for? – miensol Aug 05 '16 at 09:13
  • 1
    I would not like to have unnecessary, empty instances. I know the easiest solution is to have nullable lambda but that implies ugly constructions ```action?.invoke()```. – Paweł Byszewski Aug 05 '16 at 09:47
  • @PawełByszewski what are your concerns about ```class Test1(val action: () -> Unit = {})```? – ruX Aug 05 '16 at 11:00
  • You asked for opinion between two subjective answers. Therefore the answer is your question: use null if you like dealing with nulls, or use empty if you want to have empty behavior when the value is missing. The same question could be asked about "should I have a null list or empty list?" and the answer is the same "it depends on you" – Jayson Minard Aug 05 '16 at 13:14
  • Both solutions look smelly to me. Why not have two separate types: one with an action and one without? You may need to use inheritance and/or delegation to reuse some code. You might even make `action` an abstract function instead of a property. I suspect that your code will be cleaner. – mfulton26 Aug 05 '16 at 14:04
  • You may have right but I suppose there are cases where that approach is reasonable. For example DSL or example dialog window builder that follow patter well known thought a framework. Anyway questions how does Kotlin work still is waiting for answer – Paweł Byszewski Aug 05 '16 at 15:15

2 Answers2

16

It is definitely more idiomatic to pass an empty lambda rather than null as a default value for a lambda parameter.

The decompiler used in IntelliJ IDEA does not always handle Kotlin bytecode particularly well, so what you see in its output in this case does not reflect what actually happens. In reality, the empty lambda will be compiled to a singleton nested class implementing the corresponding FunctionN interface with an empty body, and the singleton instance will be used as the default value.

See my talk slides for more information on how default parameters are implemented in Kotlin.

yole
  • 92,896
  • 20
  • 260
  • 197
  • 4
    How to check if lambda is empty? – Sunstrike Aug 21 '17 at 14:05
  • @Sunstrike There is no way to do that. Why do you think you need that? – yole Aug 21 '17 at 17:52
  • 1
    Opened a question https://stackoverflow.com/questions/45799825/how-to-check-lambda-emptiness-in-kotlin and probably got solution – Sunstrike Aug 21 '17 at 17:55
  • Kotlin newbie here. Is it stupid to set an empty lambda (to a variable that holds lambda stuff) "just because to release resources" after I'm done with the lambda? – Sevastyan Savanyuk Sep 25 '17 at 14:47
  • 1
    "_It is definitely more idiomatic to pass an empty lambda_" - I disagree. Since in kotlin nullability is a first class citizen and the clear indication of a missing value, I would pass null as the default argument. It also has the upside, that it can be easily checked and handled and you don't expect that the lambda does something useful - especially for lambdas with a return value. – Mathias Henze May 10 '20 at 13:01
  • I disagree with you Yole. I'd also add to what @MathiasHenze well pointed out, that empty lambdas consume memory and processing time. And it's not "just" one parameter. One project is made out of hundreds of thousands of "just one parameters" – Natan Lotério Jul 28 '23 at 08:07
13

Look at the last parameter of the exposed function:

internal fun showDialog(title: String, message: String? = null, okButtonAction: () -> Unit, koButtonAction:() -> Unit = {}) { //do things..... }
Michiel
  • 180
  • 2
  • 14
Catluc
  • 1,775
  • 17
  • 25