고차 함수와 커링
유연하고 재사용 가능한 코드를 만들기 위해 고차 함수와 커링 같은 고급 함수형 개념을 살펴봅니다.
고차 함수와 커링은(는) CoddyKit의 무료 Scala for Backend Engineering & Functional Programming 강의입니다. 이것은 3개 중 2번째 강의입니다. 아래에서 전체 강의를 무료로 읽을 수 있으며, 내장 코드 에디터와 24/7 AI 튜터와 함께 브라우저에서 직접 실습할 수 있습니다. 이 강의는 Scala for Backend Engineering & Functional Programming 학습 경로의 일부이며, 진행 상황이 웹과 CoddyKit 앱에 동기화됩니다. Scala for Backend Engineering & Functional Programming 강의에는 총 3개의 강의가 포함되어 있습니다.
고차 함수 알아보기
레슨 2에 오신 것을 환영합니다! 함수형 프로그래밍에서 함수는 매우 강력합니다. 함수는 값을 계산하는 데만 사용하는 것이 아니라 다른 데이터와 마찬가지로 다룰 수도 있습니다.
즉, 함수를 다른 함수에 인수로 전달하거나 함수의 결과로 반환할 수도 있습니다. 함수가 이렇게 동작하면 이를 고차 함수(HOF)라고 합니다.
- HOF는 하나 이상의 함수를 인수로 받습니다.
- HOF는 함수를 결과로 반환합니다.
- 또는 두 가지 모두를 수행합니다!
HOF 사용하기: `map`
Scala에서 가장 일반적으로 사용되는 HOF 중 하나는 map입니다. map은 주어진 함수를 각 컬렉션 요소에 적용하여 각 요소를 변환하고, 새로운 컬렉션을 반환합니다.
다음의 간단한 예제를 실행해 보세요.
object Main {
def main(args: Array[String]): Unit = {
val numbers = List(1, 2, 3)
val doubledNumbers = numbers.map(x => x * 2)
println(s"Original: $numbers")
println(s"Doubled: $doubledNumbers")
}
}HOF 사용하기: `filter`
또 다른 유용한 HOF는 filter입니다. filter는 주어진 조건(불리언을 반환하는 함수)을 만족하는 요소를 컬렉션에서 선택하여 새로운 컬렉션을 만듭니다.
filter를 사용하여 짝수를 찾는 방법은 다음과 같습니다.
object Main {
def main(args: Array[String]): Unit = {
val allNumbers = List(1, 2, 3, 4, 5, 6)
val evenNumbers = allNumbers.filter(x => x % 2 == 0)
println(s"All: $allNumbers")
println(s"Even: $evenNumbers")
}
}나만의 HOF 정의하기
내장된 HOF만 사용할 수 있는 것은 아닙니다! 다른 함수를 매개변수로 받는 함수를 직접 정의할 수도 있습니다. 함수 타입의 구문은 (InputType => ReturnType)입니다.
이 예제에서는 Int와 다른 함수 op를 받는 applyOperation 함수를 정의합니다. op는 Int를 받아 Int를 반환합니다.
object Main {
// A HOF that applies an operation to a number
def applyOperation(x: Int, op: Int => Int): Int = {
op(x)
}
def main(args: Array[String]): Unit = {
val result = applyOperation(10, _ * 3) // Pass an anonymous function
println(s"Result of 10 * 3: $result")
val anotherResult = applyOperation(7, _ + 5)
println(s"Result of 7 + 5: $anotherResult")
}
}익명 함수와 축약형
HOF에 함수를 전달할 때는 흔히 익명 함수(람다라고도 함)를 사용합니다. Scala는 익명 함수를 간결하게 작성하는 방법을 제공합니다.
x => x * 2: 완전한 형태의 익명 함수입니다._ * 2: 매개변수가 하나인 익명 함수의 축약형입니다.
두 방식 모두 자주 사용되며 코드를 더 짧고 읽기 쉽게 만들어 줍니다.
object Main {
def main(args: Array[String]): Unit = {
val numbers = List(10, 20, 30)
// Using full anonymous function syntax
val dividedByTwo = numbers.map(x => x / 2)
println(s"Divided by two: $dividedByTwo")
// Using shorthand `_` syntax
val plusOne = numbers.map(_ + 1)
println(s"Plus one: $plusOne")
}
}커링 소개
커링은 여러 인수를 받는 함수를 각각 하나의 인수를 받는 함수들의 연속으로 변환하는 기법입니다.
이름은 논리학자 Haskell Curry의 이름에서 유래했습니다. Scala에서는 여러 매개변수 목록을 사용하는 함수가 자동으로 커링됩니다.
f(arg1, arg2) 대신 f(arg1)(arg2)와 같이 작성합니다.
커링 예제: 여러 매개변수 목록
커링이 실제로 어떻게 동작하는지 살펴보겠습니다. add가 두 개의 서로 다른 매개변수 목록으로 인수를 받는다는 점에 주목하세요.
이렇게 하면 함수의 일부만 적용하여 일부 인수를 고정한 새로운 함수를 만들 수 있습니다.
object Main {
// A curried function with two parameter lists
def add(a: Int)(b: Int): Int = {
a + b
}
def main(args: Array[String]): Unit = {
// Call the function normally
println(s"5 + 3 = ${add(5)(3)}")
// Partially apply the first argument
val addFive = add(5)_ // `_` tells Scala to treat it as a partially applied function
println(s"5 + 10 = ${addFive(10)}")
println(s"5 + 20 = ${addFive(20)}")
}
}커링의 장점
커링을 사용하는 이유는 무엇일까요? 커링은 함수형 프로그래밍에서 다음과 같은 여러 장점을 제공합니다.
- 부분 적용: 일부 인수를 고정하여 함수의 특화된 버전을 만들 수 있습니다. 이를 통해 코드 재사용성이 향상됩니다.
- 함수 합성: 커링된 함수는 다른 함수와 합성하기가 더 쉬운 경우가 많습니다.
- 타입 추론: 특히 복잡한 제네릭 타입을 다룰 때 Scala의 타입 추론에 도움이 될 수 있습니다.
사용자 지정 로거에 커링 적용하기
같은 핵심 로직을 사용하면서 수준별로 서로 다른 로깅 함수를 만들고 싶다고 가정해 보겠습니다(예: INFO, ERROR). 이럴 때 커링이 매우 유용합니다!
일반적인 log 함수를 정의한 다음, 이를 부분 적용하여 특정 로거를 만들 수 있습니다.
object Main {
def log(level: String)(message: String): Unit = {
println(s"[$level] $message")
}
def main(args: Array[String]): Unit = {
// Create specialized loggers using partial application
val infoLogger = log("INFO")_
val errorLogger = log("ERROR")_
infoLogger("User logged in successfully.")
errorLogger("Failed to connect to database!")
}
}빠른 확인: HOF와 커링
다음 Scala 코드 조각을 살펴보세요.
def calculate(x: Int)(y: Int, op: (Int, Int) => Int): Int = {
op(x, y)
}
val add = (a: Int, b: Int) => a + b
val multiply = (a: Int, b: Int) => a * b
val result1 = calculate(10)(5, add)
val result2 = calculate(2)(3, multiply)result1과 result2의 값은 무엇일까요?
복습: HOF와 커링
잘하셨습니다! 함수형 프로그래밍의 강력한 개념 두 가지를 살펴보았습니다.
- 고차 함수(HOF): 다른 함수를 인수로 받거나 결과로 반환할 수 있는 함수입니다.
map과filter처럼 유연하고 재사용 가능한 코드를 작성할 수 있게 해 줍니다. - 커링: 여러 인수를 받는 함수를 각각 하나의 인수를 받는 함수들의 연속으로 변환하는 기법입니다. 부분 적용과 특화된 함수 생성에 매우 유용합니다.
이러한 개념은 표현력이 높고 모듈화된 Scala 코드를 작성하는 데 기본이 됩니다!
자주 묻는 질문
“고차 함수와 커링” 강의는 무료인가요?
네 — “고차 함수와 커링” 전체 내용을 이 웹사이트에서 무료로 읽을 수 있습니다. 인터랙티브하게 실습하려면(내장 코드 에디터와 24/7 AI 튜터), CoddyKit PRO로 업그레이드하면 Scala for Backend Engineering & Functional Programming 강의 전체를 잠금 해제할 수 있습니다. Scala for Backend Engineering & Functional Programming 강의에는 총 3개의 강의가 포함되어 있습니다.
“고차 함수와 커링”에서 뭘 배우나요?
유연하고 재사용 가능한 코드를 만들기 위해 고차 함수와 커링 같은 고급 함수형 개념을 살펴봅니다. 브라우저에서 직접 실행하는 실습 코드로 Scala for Backend Engineering & Functional Programming을(를) 배우며, 24/7 AI 튜터가 강의를 진행하면서 질문에 답변해줍니다.
Scala for Backend Engineering & Functional Programming을(를) 시작하는 데 경험이 필요한가요?
사전 경험은 필요하지 않습니다. CoddyKit의 Scala for Backend Engineering & Functional Programming은(는) 초급자부터 고급 학습자까지를 위해 구성되어 있으므로, 여기서 시작하거나 처음부터 시작할 수 있으며 자신의 속도대로 진행할 수 있습니다. 이것은 3개 중 2번째 강의입니다.
“고차 함수와 커링” 강의는 얼마나 걸리나요?
대부분의 CoddyKit 강의는 약 5~10분이 소요됩니다. 각 강의는 간결하고 인터랙티브하여 꾸준한 진행이 가능하며, 웹과 앱에서 중단한 부분부터 바로 시작할 수 있습니다.
이 Scala for Backend Engineering & Functional Programming 강의에서 코드를 작성하고 실행할 수 있나요?
네. 모든 Scala for Backend Engineering & Functional Programming 강의에는 내장 코드 에디터가 포함되어 있으므로, 브라우저에서 바로 실제 코드를 작성하고 실행한 후 즉시 AI 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.
이 강의의 모든 강의
- 일급 값으로서의 함수
- 고차 함수와 커링
- 불변성과 부수 효과