package ScopeFunctions
//스코프란? : 변수, 객체가 인식되는 범위
//전역 스코프 (global scope) : 프로그램 어디서나 접근 가능
//지역 스코프 (local scope) : 정의된 블록 안에서 접근 가능
//스코프 함수 : 객체에 대한 임시 스코프를 생성하고, 그안에서 코드가 돌아갈 수 있게끔 해주는 함수
//임시 스코프 안에서는 그 객체를 it, this 등으로 호출하면 되기 때문에 코드가 간결해짐
//스코프 함수는 5개가 있음, let, apply, run, also, with
//Let
//fun sendNotification(recipientAddress: String): String {
// println("Yo $recipientAddress!")
// return "Notification sent!"
//}
//
//fun getNextAddress(): String {
// return "sebastian@jetbrains.com"
//}
//
//fun main() {
// val address: String? = getNextAddress()
//
// //let을 사용하면 호출한 객체를 let 스코프 안에서 다시 사용할 수 있음
// //아래 코드에선 널비스 연산자를 사용해서 address가 null이면 null값을 반환하고
// //null이 아니라면 스코프 함수 let이 실해오디어 address를 인자삼아 람다의 내용이 실행됨
// //이렇게 작성하면 confirm을 재활용 할 수 있음
// val confirm = address?.let {
// sendNotification(it)
// }
//}
//Apply
//객체를 생성할 때 바로 초기화를 하고싶다면 사용하는 함수이다.
//class Client() {
// var token: String? = null
// fun connect() = println("connected!")
// fun authenticate() = println("authenticated!")
// fun getData() : String {
// println("getting data!")
// return "Mock data"
// }
//}
//
//val client = Client()
//
//fun main() {
// client.token = "asdf"
// client.connect()
// client.authenticate()
// client.getData()
//}
//원래라면 위 코드와 같이
//객체 생성 -> 객체 초기화를 따로 해야하지만
//apply 스코프 함수를 이용하면
//val client = Client().apply {
// token = "asdf"
// connect()
// authenticate()
//}
//한번에 생성, 초기화를 같이할 수 있다.
//Run
//val client: Client = Client().apply {
// token = "asdf"
//}
//
//fun main() {
// val result: String = client.run {
// connect()
// authenticate()
// getData()
// }
//}
//let과 apply를 합친 느낌
//마지막 줄에 있는 값을 반환해서 즉시 객체를 만들어서 값을 반환할 때 사용됨
//also
//val reversedLongUppercaseMedals: List<String> =
// medals
// .map { it.uppercase() }
// .also { println(it) }
// // [GOLD, SILVER, BRONZE]
// .filter { it.length > 4 }
// .also { println(it) }
// // [SILVER, BRONZE]
// .reversed()
//also는 람다를 실행시키고 객체를 반환함
//로깅이나, 흐름에 영향을 주지않는 작업에서 많이 쓰임
//With
//with는 스코프 함수중에 유일하게 확장 함수가 아님
//val canvas = Canvas()
//with(canvas) {
// text(10, 10, "Foo")
// rect(20, 30, 100, 50)
// circ(40, 60, 25)
// // ... 객체 이름 없이 멤버 함수 호출
//}
//with는 객체를 인자로 받아 그 객체 있는 함수들을 한번에 실행 시킬수 있음
//사용하면 코드가 간결해짐