TIL

1. scope function이란 무엇인가

fun printPerson(person: Person?) {
  if (person != null) {
    println(person.name)
    println(person.age)
  }
}

// scope function 사용 코드
fun printPerson(person: Person?) {
  persln?.let {
    println(it.name)
    println(it.age)
  }  
}
inline fun <T, R> T.let(block: (T) -> R): R {
  return block(this)
}

2. scope function의 분류

  it 사용 this 사용
람다의 결과 반환 let run
객체 자체 반환 also apply
val value1 = person.let { it.age } // age 반환
val value2 = person.run { this.age } // age 반환

val value3 = person.also { it.age } // Person 반환
val value4 = person.apply { this.age } // Person 반환
val value1 = person.let { p -> p.age }
val value2 = person.run { age }
val person = Person("does", 27)
with(person) {
  println(name)
  println(this.name)
}

3. 언제 어떤 scope fucntion을 사용해야 할까

let

val strings = listOf("apple", "car")
strings.map { it.length }
  .filter { it > 3 }
  .let(::println) // { lengths -> println(lengths) }
val length = str?.let {
  println(it.uppercase())
  it.length
}

run

val person = Person("does", 27).run(personRepository::save)

apply

// 모종의 이유로 Person 생성자에 hobby는 초기에 받지 않고
// 나중에 추가적으로 입력하는 경우가 있을 수 있다.
// 테스트 픽스처 설정 시 한 번에 넣어주고 싶을 때 사용 가능

fun createPerson(
  name: String,
  age: Int,
  hobby: String
): Person {
  return Person(
    name = name,
    age = age,
  ).apply {
    this.hobby = hobby
  }
}

also

mutableListOf("one", "two", "three")
  .also { println("four 추가 이전 지금 값 : $it") }
  .add("four")

with

return with(person) { 
  PersonDto( // this를 생략할 수 있어 필드가 많아도 코드가 간결해진다.
    name = name,
    age = age
  )
}

4. scope function과 가독성

// 1번 코드
if (person != null && person.isAdult) {
  view.showPerson(person)
} else {
  view.showError()
}

// 2번 코드
person?.takeIf { it.isAdult }
  ?.let(view::showPerson)
  ?: view.showError()