🔥 연습문제 - 피보나치 수열

330자
5분

함수형 프로그래밍에서는 클로저(Closure)라는 개념이 자주 등장해요. 클로저는 함수 내부에 상태를 가지고 있는 함수를 말하는데요. 이번에는 클로저를 활용하여 피보나치 수열을 반환하는 함수를 만들어 볼 거예요.

피보나치 수열은 0과 1로 시작하며, 다음 수는 바로 앞의 두 수의 합이 되는 수열이에요. 예를 들어 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, ... 와 같은 식으로 나타낼 수 있죠.

Go 언어에서는 다음과 같이 클로저를 사용하여 피보나치 수열을 반환하는 함수를 구현할 수 있어요.

go
package main
 
import "fmt"
 
// fibonacci는 피보나치 수열을 반환하는 함수를 반환하는 함수예요.
func fibonacci() func() int {
    // 피보나치 수열의 첫 번째와 두 번째 값을 초기화해요.
    a, b := 0, 1
 
    // 익명 함수를 반환해요.
    return func() int {
        // 현재 피보나치 수열의 값을 저장할 변수를 선언해요.
        curr := a
        // 다음 피보나치 수열의 값을 계산해요.
        a, b = b, a+b
        // 현재 피보나치 수열의 값을 반환해요.
        return curr
    }
}
 
func main() {
    // 피보나치 수열을 반환하는 함수를 호출해요.
    f := fibonacci()
    // 피보나치 수열의 첫 10개 값을 출력해요.
    for i := 0; i < 10; i++ {
        fmt.Println(f())
    }
}
 
go
package main
 
import "fmt"
 
// fibonacci는 피보나치 수열을 반환하는 함수를 반환하는 함수예요.
func fibonacci() func() int {
    // 피보나치 수열의 첫 번째와 두 번째 값을 초기화해요.
    a, b := 0, 1
 
    // 익명 함수를 반환해요.
    return func() int {
        // 현재 피보나치 수열의 값을 저장할 변수를 선언해요.
        curr := a
        // 다음 피보나치 수열의 값을 계산해요.
        a, b = b, a+b
        // 현재 피보나치 수열의 값을 반환해요.
        return curr
    }
}
 
func main() {
    // 피보나치 수열을 반환하는 함수를 호출해요.
    f := fibonacci()
    // 피보나치 수열의 첫 10개 값을 출력해요.
    for i := 0; i < 10; i++ {
        fmt.Println(f())
    }
}
 

위 코드에서 fibonacci 함수는 피보나치 수열을 반환하는 클로저 함수를 반환해요. 클로저 함수 내부에서는 ab 변수를 사용하여 피보나치 수열의 값을 계산하고 있어요.

main 함수에서는 fibonacci 함수를 호출하여 피보나치 수열을 반환하는 클로저 함수를 얻어요. 그리고 for 루프를 사용하여 피보나치 수열의 첫 10개 값을 출력하고 있죠.

위 코드를 실행하면 다음과 같은 결과를 얻을 수 있어요.

text
0
1
1
2
3
5
8
13
21
34
text
0
1
1
2
3
5
8
13
21
34

이렇게 클로저를 사용하면 함수 내부에 상태를 가지고 있는 함수를 만들 수 있어요. 피보나치 수열을 반환하는 함수 외에도 다양한 용도로 클로저를 활용할 수 있답니다.

lecture image

위 다이어그램은 fibonacci 함수가 동작하는 과정을 나타내고 있어요. fibonacci 함수를 호출하면 클로저 함수가 반환되고, 클로저 함수 내부에서는 ab 변수를 초기화한 후 익명 함수를 반환하죠. 익명 함수에서는 현재 피보나치 수열의 값을 저장하고, 다음 피보나치 수열의 값을 계산한 후 현재 피보나치 수열의 값을 반환하고 있어요.

클로저를 활용하면 이렇게 함수 내부에 상태를 가지고 있는 함수를 만들 수 있답니다. 앞으로도 클로저를 활용하여 다양한 문제를 해결해 보면 좋겠죠?

YouTube 영상

채널 보기
입력을 전처리하는 Functor - Contravariant와 contramap 이해하기 | 프로그래머를 위한 카테고리 이론
NestJS 커스텀 데코레이터 인자 전달 및 파이프 검증 활용법 | NestJS 가이드
매번 ValidationPipe 복붙하세요? NestJS 전역 파이프로 한 번에 해결하기 | NestJS 가이드
함수 객체의 보편적 구성 | 프로그래머를 위한 카테고리 이론
NestJS 역할 기반 접근 권한 부여 - Guard, Reflector | NestJS 가이드
함수 타입과 Hom-Set 이해하기 | 프로그래머를 위한 카테고리 이론
미들웨어 vs 가드, 왜 NestJS에서는 가드가 더 똑똑할까? | NestJS 가이드
인터셉터와 RxJS로 캐시 시스템 구축하기 | NestJS 가이드