3

Often, I have the following pattern:

a.x()
a.y()
a.z()

Kotlin offers a convenient alternative:

a.run { x(); y(); z() }

Sometimes I have a pattern like this:

a.x()
b.x()
c.x()

I want to write something like this:

applyTo(a, b, c) { it.x() }

So I might implement the following:

fun <P> applyTo(vararg ps: P, fx: (P) -> Unit) = ps.forEach { fx(it) }

Or alternately, something like this:

::x.eachOf(a, b, c)

So I could implement the function:

fun <P, R> ((P) -> R).eachOf(vararg p: P) = p.forEach { this(it) }

Is there a way to invoke a shared method on multiple receivers using the standard library, or a better way to shorten Pattern #2?

breandan
  • 1,965
  • 26
  • 45

2 Answers2

4

Just use a list:

listOf(a, b, c).forEach { it.x() }
voddan
  • 31,956
  • 8
  • 77
  • 87
  • 1
    `listOf` was my first guess, and probably the best one. I wish Kotlin had collection literals. All this extra ceremony just to avoid six extra characters. Thanks! – breandan Dec 28 '17 at 13:00
  • 1
    `All this extra ceremony just to avoid six extra characters` that's what I think when I see a language WITH collection literals :) – voddan Dec 28 '17 at 13:42
  • 2
    They're coming (collection literals)... 1.2 introduced them for arrays in Annotations, and did some behind the scenes work to prepare for general introduction. – Mikezx6r Dec 28 '17 at 17:10
4

I assume your a,b,c are of the same type. You can modify your applyTo to accept a lambda with receiver and make the call look like in run:

fun <P> applyTo(vararg ps: P, fx: P.() -> Unit) = ps.forEach { it.fx() }
//call without it.x()
applyTo(a, b, c) { x() }

Your second solution is interesting but not very readable imho. Would not do that.

s1m0nw1
  • 76,759
  • 17
  • 167
  • 196