# applyIf and letIf?

**URL:** <https://discuss.kotlinlang.org/t/applyif-and-letif/26390>\
**Category:** Libraries\
**Created:** [February 15, 2023, 12:12pm UTC](https://discuss.kotlinlang.org/t/applyif-and-letif/26390 "2023-02-15T12:12:20Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![BoD](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.kotlinlang.org/bod/32/9026_2.png) [@BoD](https://discuss.kotlinlang.org/u/BoD)\
**Post date:** [February 15, 2023, 12:12pm UTC](https://discuss.kotlinlang.org/t/applyif-and-letif/26390/1 "2023-02-15T12:12:20Z")

</div>

I very often find myself doing this:

```kotlin
foo = bar
  .let {
    if (someCondition) {
      it.baz()
    } else {
      it
    }
  }

```

and similarly with `apply`:

```kotlin
foo = bar
  .apply {
    if (someCondition) {
      baz()
    }
  }

```

Wouldn’t it be great if the stdlib had `letIf` and `applyIf`?

```kotlin
foo = bar
  .letIf(someCondition) {
    it.baz()
  }

foo = bar
  .applyIf(someCondition) {
    baz()
  }

```

I realize this can very easily be added to my own projects, but I think there’s a case to have this in the standard library directly, as it is probably a very common use case.

Thoughts?

---

<div class="post-metadata">

**Author:** ![jacek.s.gajek](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.kotlinlang.org/jacek.s.gajek/32/8517_2.png) [@jacek.s.gajek](https://discuss.kotlinlang.org/u/jacek.s.gajek)\
**Post date:** [February 15, 2023, 12:25pm UTC](https://discuss.kotlinlang.org/t/applyif-and-letif/26390/2 "2023-02-15T12:25:02Z")

</div>

```auto
foo = bar
   .takeIf { condition }
  ?.let { it.baz() }
  ?: it

```

```auto
foo = bar
   .takeIf { condition }
  ?.apply { baz() }

```

---

<div class="post-metadata">

**Author:** ![BoD](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.kotlinlang.org/bod/32/9026_2.png) [@BoD](https://discuss.kotlinlang.org/u/BoD)\
**Post date:** [February 15, 2023, 12:39pm UTC](https://discuss.kotlinlang.org/t/applyif-and-letif/26390/3 "2023-02-15T12:39:29Z")

</div>

@jacek.s.gajek This is one possible alternative way to do this, but I would argue that it is not as readable or concise as my proposed syntax, nor as readable or concise as the original with ifs inside let/apply.

---

<div class="post-metadata">

**Author:** ![frozenice](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.kotlinlang.org/frozenice/32/7436_2.png) [@frozenice](https://discuss.kotlinlang.org/u/frozenice)\
**Post date:** [February 16, 2023, 8:24am UTC](https://discuss.kotlinlang.org/t/applyif-and-letif/26390/4 "2023-02-16T08:24:08Z")

</div>

A valid idea, but what if `someCondition` needs to invoke some property or method of `bar`? In your original example `someCondition` ist inside `let` / `apply` so it has access to `it` / `this`. That is also the ‘spirit’ of `takeIf`: the subject is in scope, you don’t need to write `bar` again.

One solution could be that `letIf` / `applyIf` take 2 closures, but that isn’t very Kotlin-y (`.letIf({ ... }) { ... }` 🙄).

I would do it the way @jacek.s.gajek did or - if it’s more complex / not quite readable at a glance - do it like your original example.

---

<div class="post-metadata">

**Author:** ![BoD](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.kotlinlang.org/bod/32/9026_2.png) [@BoD](https://discuss.kotlinlang.org/u/BoD)\
**Post date:** [February 16, 2023, 8:45am UTC](https://discuss.kotlinlang.org/t/applyif-and-letif/26390/5 "2023-02-16T08:45:02Z")

</div>

Good point @frozenice - I guess if this can’t be used when the condition depends on the receiver, then it may not be worth adding it to the stdlib then.

Just for more context, I find I need this pattern often with Jetpack Compose, where applying modifiers in a chain happens a lot:

```kotlin
    Component(
        modifier = Modifier
            .horizontalScroll(scrollState)
            .wrapContentSize()
            .letIf(isLargeScreen) {
              it.padding(8.dp)
            }
    )

```

---

<div class="post-metadata">

**Author:** ![frozenice](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.kotlinlang.org/frozenice/32/7436_2.png) [@frozenice](https://discuss.kotlinlang.org/u/frozenice)\
**Post date:** [February 16, 2023, 8:43pm UTC](https://discuss.kotlinlang.org/t/applyif-and-letif/26390/6 "2023-02-16T20:43:18Z")

</div>

I haven’t used Jetpack Compose yet, but isn’t `Modifier` a builder, i.e. it returns itself and you can set multiple modifications? A `let` or `letIf` doesn’t fit there in my opinion, because you’d want to return the builder and not something from your closure, so you can chain further. Your `applyIf` would fit better there, I think.

I would probably do this with `apply` / `also` (you can group multiple conditions in there, too):

```kotlin
Component(
  modifier = Modifier
    .horizontalScroll(scrollState)
    .wrapContentSize()
    .apply {
      if (isLargeScreen) {
        padding(8.dp)
      }

      if (someOtherCondition) {
        other("stuff")
      }
    }
)

```

---

<div class="post-metadata">

**Author:** ![arocnies](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.kotlinlang.org/arocnies/32/5143_2.png) [@arocnies](https://discuss.kotlinlang.org/u/arocnies)\
**Post date:** [February 16, 2023, 10:10pm UTC](https://discuss.kotlinlang.org/t/applyif-and-letif/26390/7 "2023-02-16T22:10:36Z")

</div>

Why the “let”? Kotlin has if-expressions instead of if-statements.

So you can:

```run-kotlin
fun main() {
  var foo: Any? = null
  val bar = object { fun baz() = Unit }
  val someCondition = true

//sampleStart
  foo = if (someCondition) {
      bar.baz()
    } else {
      bar
    }
//sampleEnd
}

```

EDIT:  
Since it seems other people have the same reaction to OPs original idea as me, I figure I’ll reply to myself for “why not use if-expression”.

While the use-case of “foo = …” is solved well by an if-expression, when using a call chain (i.e. when using a fluent API) you may want to place the condition somewhere other than at the assignment. Here’s a more relevant [example from OP](https://discuss.kotlinlang.org/t/applyif-and-letif/26390/5).

---

<div class="post-metadata">

**Author:** ![BoD](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.kotlinlang.org/bod/32/9026_2.png) [@BoD](https://discuss.kotlinlang.org/u/BoD)\
**Post date:** [February 22, 2023, 10:43am UTC](https://discuss.kotlinlang.org/t/applyif-and-letif/26390/8 "2023-02-22T10:43:48Z")

</div>

(Sorry for the late reply.)

@frozenice `Modifier` is used like a builder, but actually it is immutable. In other words, you need to explicitly return the result of each call in the chain, otherwise it will be lost.

Another example I think would be some chain of `Flow` operators:

```kotlin
val result = someFlow
  .filter { it.name == query }
  .letIf(includeTitle) { 
    it.filter { it.title == query } 
  } 
  .letIf(includeDesc) { 
    it.filter { it.desc == query } 
  } 

```

In that context, I guess `applyIf` doesn’t really work, and `letIf` would be the good fit.

---

<div class="post-metadata">

**Author:** ![broot](https://avatars.discourse-cdn.com/v4/letter/b/a88e57/32.png) [@broot](https://discuss.kotlinlang.org/u/broot)\
**Post date:** [February 22, 2023, 11:34am UTC](https://discuss.kotlinlang.org/t/applyif-and-letif/26390/9 "2023-02-22T11:34:56Z")

</div>

Wouldn’t it be cleaner to do?

```kotlin
.filter { it.name == query }
.filter { !includeTitle || it.title == query }
.filter { !includeDesc || it.desc == query }

```

Or even:

```kotlin
.filter {
    if.name == query
        && (!includeTitle || it.title == query)
        && (!includeDesc || it.desc == query)
}

```

You can argue your code is a little better for the performance as it checks conditions only once and creates an “execution plan” accordingly.

But generally I agree, it could be sometimes helpful to map a value depending on a condition. But I think the condition would have to be a lambda, not boolean. Providing a boolean there doesn’t seem very Kotlin-ish to me.

---

<div class="post-metadata">

**Author:** ![BoD](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.kotlinlang.org/bod/32/9026_2.png) [@BoD](https://discuss.kotlinlang.org/u/BoD)\
**Post date:** [February 22, 2023, 6:36pm UTC](https://discuss.kotlinlang.org/t/applyif-and-letif/26390/10 "2023-02-22T18:36:26Z")

</div>

@broot I guess, but as noted previously, with 2 lambdas, you can’t benefit from trailing lambdas﻿ out of parentheses anymore… On the other hand, we could imagine having 2 versions of `letIf`, one that takes a boolean and one that takes a lambda.

---

<div class="post-metadata">

**Author:** ![arocnies](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.kotlinlang.org/arocnies/32/5143_2.png) [@arocnies](https://discuss.kotlinlang.org/u/arocnies)\
**Post date:** [February 22, 2023, 7:37pm UTC](https://discuss.kotlinlang.org/t/applyif-and-letif/26390/11 "2023-02-22T19:37:39Z")

</div>

Idk, personally, I’d prefer a boolean–but even more than that, I’d hope any complex chained lambda logic should be factored into a well-named function. Just like you factor out the if-logic.

For example

```kotlin
// ...
Component(
  modifier = Modifier
    .horizontalScroll(scrollState)
    .wrapContentSize()
    .apply {
      if (isLargeScreen) {
        padding(8.dp)
      }

      if (someOtherCondition) {
        other("stuff")
      }
    }
)

```

Becomes

```kotlin
Component(
  modifier = Modifier
    .horizontalScroll(scrollState)
    .wrapContentSize()
    .withSizeAdjustedPadding()
    .applyOtherCondition()
)

```

This is the same thing you expect to do when you’re cleaning up a function that does more than one thing–when that “other thing” is deciding what padding, deciding which file to load, or deciding some other condition, the if-block may get factored into its own function.

This example:

```kotlin
val result = someFlow
  .filter { it.name == query }
  .letIf(includeTitle) { 
    it.filter { it.title == query } 
  } 
  .letIf(includeDesc) { 
    it.filter { it.desc == query } 
  } 

```

might be refactored to

```kotlin
val result = someFlow
  .filter { it.name == query }
  .populateTextFields() // or maybe "addIncludedFields()"?
  .onEach { functionResponsibleForConditionalLogic(it) } // <-- instead of making them sequence functions, this is an option.

```

There may still be a use for dedicated `letIf` but I’d still expect long chains of functional calls to be extracted into functions. Once you’re dealing with the smaller footprint, it makes it easy to implement without a letIf.

---

<div class="post-metadata">

**Author:** ![broot](https://avatars.discourse-cdn.com/v4/letter/b/a88e57/32.png) [@broot](https://discuss.kotlinlang.org/u/broot)\
**Post date:** [February 22, 2023, 8:27pm UTC](https://discuss.kotlinlang.org/t/applyif-and-letif/26390/12 "2023-02-22T20:27:22Z")

</div>

> [@BoD](#):
>
> @broot I guess, but as noted previously, with 2 lambdas, you can’t benefit from trailing lambdas out of parentheses anymore…

Well, we still can put the second lambda out of parentheses. Assuming we really want to do this, because it may look somehow strange.

I agree, we should generally avoid having two lambdas, but this is not entirely wrong and it is used even in the stdlib. For example `groupBy()` with separate key selector and value transformer; or `Result.fold()` where we can map both the success and failure.

I personally don’t do this very often, but sometimes I create such functions with two lambdas. If there is asymmetry between lambdas, so one of them is considered generally smaller, lighter or “initial”, then I place it as the first. Then depending on the case I use different styles when invoking them, again depending on symmetry and sizes of lambdas. Some examples:

```kotlin
users.associateBy({ it.id }, { it.name })

file.letIf({ it.isRelative }) {
    it.resolveToAbsoluteFile()
}

result.fold(
    onSuccess = {
        ...
    },
    onFailure = {
        ...
    },
)

```

Again, I don’t do this very often and usually it is better to avoid this, for example by chaining multiple higher-order functions, but sometimes it is useful.

Anyway, of course having two overloaded versions: with lambda and boolean; is even better.

---

<div class="post-metadata">

**Author:** ![dalewking](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.kotlinlang.org/dalewking/32/1496_2.png) [@dalewking](https://discuss.kotlinlang.org/u/dalewking)\
**Post date:** [February 22, 2023, 8:36pm UTC](https://discuss.kotlinlang.org/t/applyif-and-letif/26390/13 "2023-02-22T20:36:47Z")

</div>

The problem is what is the return type of such a function? By your example it can be the type of bar or the return type of bar.baz(). There is no guarantee in general that the types are at all related so the return type may be just `Any`. That alone I think justifies that it should not be in the standard library because it could be a source of confusion.

But that doesn’t keep you from adding it to your own project or build a utility library. I have these in my project:

```auto
inline fun <R, T : R> T.transformIf(condition: Boolean, transform: (T) -> R) =
    if (condition) transform(this) else this

inline fun <R, T : R> T.transformUnless(condition: Boolean, transform: (T) -> R) =
    transformIf(!condition, transform)

```

but looking at the uses for it I only use it one place. And that is something like this in my dependency injection code to conditionally wrap an object with a logging wrapper:

```auto
        DefaultStoreFactory().transformIf(IS_DEBUG) { LoggingStoreFactory(it, logger = instance()) }

```

It only works in this case because the two types have a common interface.

---

<div class="post-metadata">

**Author:** ![dalewking](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.kotlinlang.org/dalewking/32/1496_2.png) [@dalewking](https://discuss.kotlinlang.org/u/dalewking)\
**Post date:** [February 22, 2023, 8:47pm UTC](https://discuss.kotlinlang.org/t/applyif-and-letif/26390/14 "2023-02-22T20:47:27Z")

</div>

With your Jetpack Compose example, it would be better to define specific functions rather than more general purpose ones where return type is an issue. For example:

```auto
inline fun Modifier.thenIf(condition: Boolean, modification: Modifier.() -> Modifier) =
    if(condition) modification() else this

inline fun Modifier.thenIf(condition: Boolean, modifier: Modifier) =
    if(condition) this.then(modifier) else this

```

---

<div class="post-metadata">

**Author:** ![broot](https://avatars.discourse-cdn.com/v4/letter/b/a88e57/32.png) [@broot](https://discuss.kotlinlang.org/u/broot)\
**Post date:** [February 22, 2023, 9:24pm UTC](https://discuss.kotlinlang.org/t/applyif-and-letif/26390/15 "2023-02-22T21:24:17Z")

</div>

> [@dalewking](#):
>
> The problem is what is the return type of such a function? By your example it can be the type of bar or the return type of bar.baz(). There is no guarantee in general that the types are at all related so the return type may be just `Any`. That alone I think justifies that it should not be in the standard library because it could be a source of confusion.

Yes, but isn’t that problem pretty common when using generics and type inference in general? Some examples, starting with a little silly ones:

```kotlin
listOf(1, "a")

if (true) 1 else "a"

mapOf(1 to 1).getOrElse(1) { "a" }

listOf(1, 2, 3).ifEmpty { listOf("a", "b", "c") }

Result.success(1).recover { "a" }

Result.success(1).fold({ 1 }, { "a" })

sequence {
    yield(1)
    yield("a")
}

```

None of these will even show us a warning that we use types inconsistently. It is assumed we want the compiler to find the closest common supertype.

`getOrElse()` is a pretty similar case to `letIf()`, because there is a hidden condition (if exists) and then it either returns the value from the receiver or one generated by our lambda. Same for `ifEmpty()` and `recover()`.

---

<div class="post-metadata">

**Author:** ![BoD](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.kotlinlang.org/bod/32/9026_2.png) [@BoD](https://discuss.kotlinlang.org/u/BoD)\
**Post date:** [February 23, 2023, 8:49am UTC](https://discuss.kotlinlang.org/t/applyif-and-letif/26390/16 "2023-02-23T08:49:12Z")

</div>

It’s a very good point @dalewking!

I imagined its signature would be:

```kotlin
inline fun <T> T.letIf(condition: Boolean, block: (T) -> T): T {
  return if (condition) block(this) else this
}

```

But `let`’s signature is not to return `T`, but `R`:

```auto
inline fun <T, R> T.let(block: (T) -> R): R {
    return block(this)
}

```

Having `let` and `letIf` have this difference would probably be inconsistent and cause confusion…

I like the `tranformIf` name for this. 👍

This issue doesn’t apply (sic) to `applyIf` though - they’d both return `T` and be consistent.

---

<div class="post-metadata">

**Author:** ![Joachim.Lous](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.kotlinlang.org/joachim.lous/32/11171_2.png) [@Joachim.Lous](https://discuss.kotlinlang.org/u/Joachim.Lous)\
**Post date:** [April 10, 2025, 7:42am UTC](https://discuss.kotlinlang.org/t/applyif-and-letif/26390/17 "2025-04-10T07:42:08Z")

</div>

> The problem is what is the return type of such a function?

Why is this problem any bigger with letIf() than with let()?

---

<div class="post-metadata">

**Author:** ![dalewking](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.kotlinlang.org/dalewking/32/1496_2.png) [@dalewking](https://discuss.kotlinlang.org/u/dalewking)\
**Post date:** [April 12, 2025, 4:24pm UTC](https://discuss.kotlinlang.org/t/applyif-and-letif/26390/18 "2025-04-12T16:24:51Z")

</div>

For let it is known what the resulting type is because the transform always runs. E.g

```auto
val x: String = 5.let { it.toString() }

```

in this case the type is String because toString is always called.

But that isn’t the case for a `letIf`

```auto
val x = 5.letIf(someCondition) { it.toString() }

```

What is the type of `x`?

---

<div class="post-metadata">

**Author:** ![kyay10](https://avatars.discourse-cdn.com/v4/letter/k/c57346/32.png) [@kyay10](https://discuss.kotlinlang.org/u/kyay10)\
**Post date:** [April 12, 2025, 5:25pm UTC](https://discuss.kotlinlang.org/t/applyif-and-letif/26390/19 "2025-04-12T17:25:51Z")

</div>

It’d be `Any` here (well, actually `Comparable<*>` but whatever). The type is the supertype between `letIf`’s receiver and the return type of the block. This is analogous to `fold` vs `reduce`

---

<div class="post-metadata">

**Author:** ![Landei](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.kotlinlang.org/landei/32/9407_2.png) [@Landei](https://discuss.kotlinlang.org/u/Landei)\
**Post date:** [April 12, 2025, 5:30pm UTC](https://discuss.kotlinlang.org/t/applyif-and-letif/26390/20 "2025-04-12T17:30:31Z")

</div>

> [@dalewking](#):
>
> But that isn’t the case for a `letIf`
> 
> ```auto
> val x = 5.letIf(someCondition) { it.toString() }
> 
> ```
> 
> What is the type of `x`?

Yeah, there is an “else” case missing. I cobbled something together which does this, altough it looks awkward because I can’t use “if” and “else”. Usage looks like:

```kotlin
val s = 23
    .given{ it % 2 == 0 }
    .then { "$it is even" }
    .otherwise { "$it is odd" }

```

Of course in this case using a normal if would be easier to read, but in a long call chain it might be actually convenient.

Here is the ugly underbelly:

```kotlin
data class GivenBlock<T>(val value: T, val cond: Boolean)

sealed interface ThenBlock<out T, out R> {
    data class Success<T,R>(val result: R): ThenBlock<T, R>
    data class Failure<T,R>(val value:T): ThenBlock<T, R>
}

fun <T> T.given(cond: (T) -> Boolean): GivenBlock<T> =
    GivenBlock(this, cond(this))

fun <T, R> GivenBlock<T>.then(block: (T) -> R): ThenBlock<T,R> =
    when {
        cond -> ThenBlock.Success(block(value))
        else -> ThenBlock.Failure(value)
    }

fun <T,R> ThenBlock<T,R>.otherwise(block: (T) -> R) : R = 
    when(this) {
        is ThenBlock.Success -> result
        is ThenBlock.Failure -> block(value)
    }

```

[Next page](https://discuss.kotlinlang.org/t/applyif-and-letif/26390.md?page=2)
