스칼라 함수형 프로그래밍 - Closures(클로저)의 활용 사례와 유용한 상황
View: 168
0
0
작성자: 달빛제이크
카테고리: Scala Language
발행: 2024-06-12
수정
2024-06-21
안녕하세요. 달빛제이크입니다.
오늘은 Closure의 다양한 예제를 살펴보고 Closure를 도대체 언제 쓰면 좋을 지 이야기 해 보겠습니다.
Scala로 프로그래밍을 작성할 때 Closure는 언제 사용하면 좋을까요?
단순하게 생각해보면 Function literal이 free variable을 가지고 있는 open term이고, 이 free variable을 외부에서 선언해 줄 때 유용한 경우를 찾아보면 좋을 것 같습니다.
1. 함수 리터럴을 반환하는 함수
def makeMultiplier(factor: Int): Int => Int = (x: Int) => x * factor
val multiplier = makeMultiplier(3)
println(multiplier(10)) // 30
makeMultiplier라는 함수에 (x: Int) => x * factor 함수 리터럴이 정의되어 있습니다.
이 함수를 호출을 할 때 마다 factor 값을 달리 줄 수 있어서 곱하기라는 동일한 기능을 가졌지만 다른 일을 할 수 있게 합니다.
2. 데이터 캡슐화 및 유지
def makeCounter(): () => Int =
var count = 0
() => {
count += 1
count
}
val counter = makeCounter()
println(counter()) // 1
println(counter()) // 2
makeCounter는 () => Int 타입의 함수 리터럴을 반환하는 함수 입니다. 이 함수는 parameter를 가지고 있지 않기 때문에 외부에서 어떤 값도 전달할 수 없습니다. 함수 내부에 있는 함수 리터럴 자체도 parameter를 가지고 있지 않습니다. 대신 count라는 free variable를 가지고 있어 외부와 단절된 채 이 함수 리터럴이 호출 될 때마다 1을 더하는 일만 반복하게 됩니다. 즉, makeCounter 내부에 있는 함수 리터럴은 캡슐화 되어 있고 재 호출이 있기 전까지는 값이 유지되는 상태가 됩니다.
3. 콜백
def registerCallback(callback: () => Unit): Unit =
println("Callback registered")
callback()
var name = "Scala"
val callback = () => println(s"Hello, $name!")
registerCallback(callback)
// Output:
// Callback registered
// Hello, Scala!
name = "World"
registerCallback(callback)
// Output:
// Callback registered
// Hello, World!
registerCallback 함수의 Parameter로 () => Unit 타입의 함수 리터럴을 만들어 넘깁니다. () => println(s"Hello, $name!")에서 name 변수가 free variable로 "Scala"에 binding 되어 있습니다. callback 변수에 함수 리터럴을 작성하고 parameter로 넘기면서 registerCallback 함수를 호출하면 작성한 callback 함수 리터럴이 실행 됩니다. name 값을 변경하고 다시 registerCallback을 호출하면 변경된 값이 출력됩니다.
이번 글에서 Closure를 사용한 대표적인 세가지 Case에 대한 예제를 살펴 보았습니다.
Closure를 사용함으로 함수를 다른 함수에 인자로 전달하거나 반환 값으로 전달 받을 때 유연하게 형태를 변형하여 사용할 수 있습니다.
이를 통해 코드의 모듈화와 재사용성을 높이고, 강력하고 유연한 프로그램을 작성할 수 있습니다.
다음 글에서는 Special usage of functions (함수의 특별한 기능)이라는 주제로 이야기 하겠습니다.
감사합니다.
