체이닝 (Chaining)

커링 (Currying)

체이닝 상세 설명

기본 구조

class ChainExample {
    var value: Int = 0

    fun addValue(x: Int) = apply {
        value += x
    }

    fun multiplyBy(x: Int) = apply {
        value *= x
    }

    fun clear() = apply {
        value = 0
    }
}

// 사용 예시
val result = ChainExample()
    .addValue(5)
    .multiplyBy(2)
    .addValue(3)
println(result.value) // 13

안드로이드에서의 실제 사용

// View 설정
binding.titleText.apply {
    text = "제목"
    textSize = 20f
    setTextColor(Color.BLACK)
    isVisible = true
}

// RecyclerView 설정
binding.recyclerView.apply {
    layoutManager = LinearLayoutManager(context)
    adapter = UserAdapter()
    addItemDecoration(DividerItemDecoration(context, LinearLayoutManager.VERTICAL))
}

커링 상세 설명

기본 커링 함수

// 3개의 파라미터를 받는 함수를 커링하는 확장 함수
fun <P1, P2, P3, R> ((P1, P2, P3) -> R).curried(): (P1) -> (P2) -> (P3) -> R =
    { p1: P1 -> { p2: P2 -> { p3: P3 -> this(p1, p2, p3) } } }

// 사용 예시
val originalFunction = { a: Int, b: String, c: Boolean ->
    "$a - $b - $c"
}

val curriedFunction = originalFunction.curried()

// 단계별 실행
val step1 = curriedFunction(1)            // Int 인자 적용
val step2 = step1("Hello")               // String 인자 적용
val result = step2(true)                 // Boolean 인자 적용
println(result)  // "1 - Hello - true"

// 한번에 실행
val oneShot = curriedFunction(1)("Hello")(true)
println(oneShot)  // "1 - Hello - true"

실제 활용 예시

// API 요청 함수를 커링으로 구현
data class ApiConfig(
    val baseUrl: String,
    val apiKey: String,
    val timeout: Int
)

val makeApiRequest = { config: ApiConfig ->
    { endpoint: String ->
        { params: Map<String, String> ->
            // API 요청 구현
            "$config - $endpoint - $params"
        }
    }
}

// 설정 단계별 적용
val withConfig = makeApiRequest(ApiConfig("<https://api.example.com>", "key123", 5000))
val userApi = withConfig("/users")
val result = userApi(mapOf("id" to "123"))

// 로깅 시스템 예시
val createLogger = { tag: String ->
    { level: String ->
        { message: String ->
            when (level) {
                "DEBUG" -> "D/$tag: $message"
                "ERROR" -> "E/$tag: $message"
                else -> "I/$tag: $message"
            }
        }
    }
}

val userLogger = createLogger("UserActivity")
val debugLogger = userLogger("DEBUG")
println(debugLogger("User logged in"))  // "D/UserActivity: User logged in"

실제 활용: 체이닝과 커링 조합

// 체이닝으로 구현된 빌더에 커링 적용
class RequestBuilder {
    private var baseUrl: String = ""
    private var method: String = "GET"
    private var headers: Map<String, String> = emptyMap()

    fun setBaseUrl(url: String) = apply { baseUrl = url }
    fun setMethod(m: String) = apply { method = m }
    fun setHeaders(h: Map<String, String>) = apply { headers = h }

    fun build() = { endpoint: String ->
        { params: Map<String, String> ->
            // 실제 요청 구현
            "$method $baseUrl$endpoint - $params - $headers"
        }
    }
}

// 사용 예시
val apiRequest = RequestBuilder()
    .setBaseUrl("<https://api.example.com>")
    .setMethod("POST")
    .setHeaders(mapOf("Authorization" to "Bearer token"))
    .build()

val usersEndpoint = apiRequest("/users")
val result = usersEndpoint(mapOf("id" to "123"))