61
아꿈사 최기원

클로저

  • Upload
    dagri82

  • View
    458

  • Download
    0

Embed Size (px)

Citation preview

아꿈사 최기원

함수형 프로그래밍의 개념

어떻게 연산을 지연시킬까

더욱 게을러지기

다시 재귀로

함수형 프로그래밍의 개념

어떻게 연산을 지연시킬까

더욱 게을러지기

다시 재귀로

함수형 프로그래밍의 개념

순수 함수영속적 자료구조지연 평가와 재귀참조 투명성함수형 프로그래밍의 이점여섯 가지 원칙

1. 함수형 프로그래밍의 개념2. 어떻게 연산을 지연시킬까p148

순수 함수‘부수효과’가 전혀 없는 함수인자에만 의존해서 결과가 만들어지고, 반환 값으로만 외부 세계에 영향을 준다.

y = f(x)

1. 함수형 프로그래밍의 개념2. 어떻게 연산을 지연시킬까p148

1. 순수 함수2. 영속적 자료구조3. 지연 평가와 재귀4. 참조 투명성5. 함수형 프로그래밍의 이점6. 여섯 가지 원칙

순수 함수

순수 함수를 작성하기로 마음 먹었다면, 애플리케이션 전체에서 변경 불가능한 데이터를 사용해야 한다.

1. 함수형 프로그래밍의 개념2. 어떻게 연산을 지연시킬까p148

1. 순수 함수2. 영속적 자료구조3. 지연 평가와 재귀4. 참조 투명성5. 함수형 프로그래밍의 이점6. 여섯 가지 원칙

영속적(persistent) 자료구조

갱신되기 전의 데이터와 후의 데이터가 변경되지 않은 부분을 그대로‘공유하는’효율적인 접근 방식을 취한다

1. 함수형 프로그래밍의 개념2. 어떻게 연산을 지연시킬까p148

1. 순수 함수

2. 영속적 자료구조3. 지연 평가와 재귀4. 참조 투명성5. 함수형 프로그래밍의 이점6. 여섯 가지 원칙

영속적(persistent) 자료구조

(def a ’(1 2))(def b (cons 0 a))

1. 함수형 프로그래밍의 개념2. 어떻게 연산을 지연시킬까p148

1. 순수 함수

2. 영속적 자료구조3. 지연 평가와 재귀4. 참조 투명성5. 함수형 프로그래밍의 이점6. 여섯 가지 원칙

0 1 2

b

1 2

a

영속적(persistent) 자료구조

(def a ’(1 2))(def b (cons 0 a))

1. 함수형 프로그래밍의 개념2. 어떻게 연산을 지연시킬까p148

1. 순수 함수

2. 영속적 자료구조3. 지연 평가와 재귀4. 참조 투명성5. 함수형 프로그래밍의 이점6. 여섯 가지 원칙

0 1 2

b

1 2

a

영속적(persistent) 자료구조

(def a ’(1 2))(def b (cons 0 a))

1. 함수형 프로그래밍의 개념2. 어떻게 연산을 지연시킬까p148

1. 순수 함수

2. 영속적 자료구조3. 지연 평가와 재귀4. 참조 투명성5. 함수형 프로그래밍의 이점6. 여섯 가지 원칙

0 1 2

b a

지연 평가와 재귀지연 평가란, 그 표현식을 평가한 결과가 꼭 필요해질 때까지 평가를 미루는 것이다. 식을 평가한다는 것은 그표현식을 ‘실행’하는 것이다.재귀란, 함수가 그 자신을 직접 또는간접으로 호출하는 것을 말한다.

1. 함수형 프로그래밍의 개념2. 어떻게 연산을 지연시킬까p150

1. 순수 함수2. 영속적 자료구조

3. 지연 평가와 재귀4. 참조 투명성5. 함수형 프로그래밍의 이점6. 여섯 가지 원칙

지연 평가와 재귀지연 평가란, 그 표현식을 평가한 결과가 꼭 필요해질 때까지 평가를 미루는 것이다. 식을 평가한다는 것은 그표현식을 ‘실행’하는 것이다.재귀란, 함수가 그 자신을 직접 또는간접으로 호출하는 것을 말한다.

1. 함수형 프로그래밍의 개념2. 어떻게 연산을 지연시킬까p150

1. 순수 함수2. 영속적 자료구조

3. 지연 평가와 재귀4. 참조 투명성5. 함수형 프로그래밍의 이점6. 여섯 가지 원칙

지연 평가와 재귀

함수와 표현식은 평가가 지연되지 않는다. 시퀀스에 대해서는 평가가 지연된다.

1. 함수형 프로그래밍의 개념2. 어떻게 연산을 지연시킬까p150

1. 순수 함수2. 영속적 자료구조

3. 지연 평가와 재귀4. 참조 투명성5. 함수형 프로그래밍의 이점6. 여섯 가지 원칙

지연 평가와 재귀

순수 함수를 사용하면, 그 함수를 지금 호출하든 나중에 호출하든 결과에차이가 없기 때문에 평가를 지연할 수있다.

1. 함수형 프로그래밍의 개념2. 어떻게 연산을 지연시킬까p150

1. 순수 함수2. 영속적 자료구조

3. 지연 평가와 재귀4. 참조 투명성5. 함수형 프로그래밍의 이점6. 여섯 가지 원칙

참조 투명성 (referential transparency)

함수 호출 자체를 함수의 결과로 치환해도 프로그램의 행동에 영향을 미치지 않는 함수를 가리켜 ‘참조 투명성이 있는 함수’ 라고 한다.

1. 함수형 프로그래밍의 개념2. 어떻게 연산을 지연시킬까p150

1. 순수 함수2. 영속적 자료구조3. 지연 평가와 재귀

4. 참조 투명성5. 함수형 프로그래밍의 이점6. 여섯 가지 원칙

참조 투명성 (referential transparency)

순수 함수는 기본적으로 참조 투명성을 가진다.

1. 함수형 프로그래밍의 개념2. 어떻게 연산을 지연시킬까p150

1. 순수 함수2. 영속적 자료구조3. 지연 평가와 재귀

4. 참조 투명성5. 함수형 프로그래밍의 이점6. 여섯 가지 원칙

함수형 프로그래밍의 이점

‘작성’하기 쉽다.‘읽는’ 것 역시 쉽다.테스트하기 쉽다.재사용하기 쉽다.가독성이 좋다.

1. 함수형 프로그래밍의 개념2. 어떻게 연산을 지연시킬까p150

1. 순수 함수2. 영속적 자료구조3. 지연 평가와 재귀4. 참조 투명성

5. 함수형 프로그래밍의 이점6. 여섯 가지 원칙

함수형 프로그래밍의 이점

‘작성’하기 쉽다.‘읽는’ 것 역시 쉽다.테스트하기 쉽다.재사용하기 쉽다.가독성이 좋다.

1. 함수형 프로그래밍의 개념2. 어떻게 연산을 지연시킬까p150

1. 순수 함수2. 영속적 자료구조3. 지연 평가와 재귀4. 참조 투명성

5. 함수형 프로그래밍의 이점6. 여섯 가지 원칙

함수형 프로그래밍의 이점

순수 함수는 캡슐화 원칙을 철저히 지키며, 따라서 조합을 쉽게 만든다.

‘순수하지 못한 함수’들은 캡슐화를 위반하는 부수효과를 만들어 낸다.

1. 함수형 프로그래밍의 개념2. 어떻게 연산을 지연시킬까p150

1. 순수 함수2. 영속적 자료구조3. 지연 평가와 재귀4. 참조 투명성

5. 함수형 프로그래밍의 이점6. 여섯 가지 원칙

여섯 가지 원칙1. 직접 재귀를 사용하지 말자.2. recur를 사용하자.3. 규모가 큰 자료 구조는 지연 시퀀

스로 만들자.4. 필요한 부분만 평가하게 하자5. 시퀀스 라이브러리를 사용하자6. 쪼개서 정복하자.

1. 함수형 프로그래밍의 개념2. 어떻게 연산을 지연시킬까p152

1. 순수 함수2. 영속적 자료구조3. 지연 평가와 재귀4. 참조 투명성5. 함수형 프로그래밍의 이점

6. 여섯 가지 원칙

함수형 언어 정리순수 함수

‘부수효과’가 전혀 없는 함수순수 함수를 사용하면 평가를 지연할 수있다.변경 불가능한 데이터를 사용순수 함수는 기본적으로 참조 투명성을 가진다.순수 함수는 캡슐화 원칙을 지킨다.(조합)

어떻게 연산을 지연시킬까재귀꼬리 재귀recur를 이용한 자체 재귀지연 시퀀스시퀀스의 실현머리를 쓰지 않기

1. 함수형 프로그래밍의 개념2. 어떻게 연산을 지연시킬까p153

1. 함수형 프로그래밍의 개념2. 어떻게 연산을 지연시킬까p153

1. 재귀2. 꼬리 재귀3. recur를 이용한 자체 재귀4. 지연 시퀀스5. 시퀀스의 실현6. 머리를 쓰지 않기

재귀

기저 : 만들어 내려는 시퀀스 가운데 추론이 필요 없는 매우 명백한 원소귀납 규칙 : 기저를 바탕으로 추가적 원소를 만들어 내는 데 필요한 규칙

함수가 자기 자신을 호출하게 한 뒤적절한 조작을 가해, 귀납에 해당하는과정을 만들어 내는 방법이다.

1. 함수형 프로그래밍의 개념2. 어떻게 연산을 지연시킬까p153

1. 재귀2. 꼬리 재귀3. recur를 이용한 자체 재귀4. 지연 시퀀스5. 시퀀스의 실현6. 머리를 쓰지 않기

재귀, 기저; 나쁜 아이디어(defn stack-consuming-fibo [n]

(cond(= n 0) 0(= n 1) 1

:else (+ (stack-consuming-fibo (- n 1))(stack-consuming-fibo (- n 2)))))

1. 함수형 프로그래밍의 개념2. 어떻게 연산을 지연시킬까p153

1. 재귀2. 꼬리 재귀3. recur를 이용한 자체 재귀4. 지연 시퀀스5. 시퀀스의 실현6. 머리를 쓰지 않기

재귀, 귀납 규칙; 나쁜 아이디어(defn stack-consuming-fibo [n]

(cond(= n 0) 0(= n 1) 1

:else (+ (stack-consuming-fibo (- n 1))(stack-consuming-fibo (- n 2)))))

1. 함수형 프로그래밍의 개념2. 어떻게 연산을 지연시킬까p153

1. 재귀2. 꼬리 재귀3. recur를 이용한 자체 재귀4. 지연 시퀀스5. 시퀀스의 실현6. 머리를 쓰지 않기

재귀; 나쁜 아이디어(defn stack-consuming-fibo [n]

(cond(= n 0) 0(= n 1) 1

:else (+ (stack-consuming-fibo (- n 1))(stack-consuming-fibo (- n 2)))))

1. 함수형 프로그래밍의 개념2. 어떻게 연산을 지연시킬까p155

1. 재귀

2. 꼬리 재귀3. recur를 이용한 자체 재귀4. 지연 시퀀스5. 시퀀스의 실현6. 머리를 쓰지 않기

꼬리 재귀

함수가 함수 정의의 마지막 부분에서자기 자신을 호출하는 것외에 다른 조작을 가하지 않는 재귀의 형태다.

1. 함수형 프로그래밍의 개념2. 어떻게 연산을 지연시킬까p155

1. 재귀

2. 꼬리 재귀3. recur를 이용한 자체 재귀4. 지연 시퀀스5. 시퀀스의 실현6. 머리를 쓰지 않기

꼬리 재귀

; 나쁜 아이디어(defn stack-consuming-fibo [n]

(cond(= n 0) 0(= n 1) 1

:else (+ (stack-consuming-fibo (- n 1))(stack-consuming-fibo (- n 2)))))

1. 함수형 프로그래밍의 개념2. 어떻게 연산을 지연시킬까p155

1. 재귀

2. 꼬리 재귀3. recur를 이용한 자체 재귀4. 지연 시퀀스5. 시퀀스의 실현6. 머리를 쓰지 않기

꼬리 재귀

(defn tail-fibo [n](letfn [(fib

[current next n](if (zero? n)

current(fib next (+ current next) (dec n))))]

(fib 0 1 n))

1. 함수형 프로그래밍의 개념2. 어떻게 연산을 지연시킬까p155

1. 재귀

2. 꼬리 재귀3. recur를 이용한 자체 재귀4. 지연 시퀀스5. 시퀀스의 실현6. 머리를 쓰지 않기

꼬리 재귀

(defn tail-fibo [n](letfn [(fib

[current next n](if (zero? n)

current(fib next (+ current next) (dec n))))]

(fib 0 1 n))

1. 함수형 프로그래밍의 개념2. 어떻게 연산을 지연시킬까p155

1. 재귀

2. 꼬리 재귀3. recur를 이용한 자체 재귀4. 지연 시퀀스5. 시퀀스의 실현6. 머리를 쓰지 않기

꼬리 재귀

(defn tail-fibo [n](letfn [(fib

[current next n](if (zero? n)

current(fib next (+ current next) (dec n))))]

(fib 0 1 n))

1. 함수형 프로그래밍의 개념2. 어떻게 연산을 지연시킬까p155

1. 재귀

2. 꼬리 재귀3. recur를 이용한 자체 재귀4. 지연 시퀀스5. 시퀀스의 실현6. 머리를 쓰지 않기

꼬리 재귀

(defn tail-fibo [n](letfn [(fib

[current next n](if (zero? n)

current(fib next (+ current next) (dec n))))]

(fib 0 1 n))

1. 함수형 프로그래밍의 개념2. 어떻게 연산을 지연시킬까p155

1. 재귀

2. 꼬리 재귀3. recur를 이용한 자체 재귀4. 지연 시퀀스5. 시퀀스의 실현6. 머리를 쓰지 않기

C++ 버전

int fibo(int current, int next, int n){

if (n == 0)return current;

return fibo(next, current + next, n - 1);}

1. 함수형 프로그래밍의 개념2. 어떻게 연산을 지연시킬까p156

1. 재귀2. 꼬리 재귀

3. recur를 이용한 자체 재귀4. 지연 시퀀스5. 시퀀스의 실현6. 머리를 쓰지 않기

recur를 이용한 자체 재귀

자바 가상 머신에서도 자체 재귀로 최적화할 수 있다.

클로저에서 꼬리 재귀 함수는 recur를 이용하는 자체 재귀 함수로 고쳐쓸수 있다.

1. 함수형 프로그래밍의 개념2. 어떻게 연산을 지연시킬까p156

1. 재귀2. 꼬리 재귀

3. recur를 이용한 자체 재귀4. 지연 시퀀스5. 시퀀스의 실현6. 머리를 쓰지 않기

recur를 이용한 자체 재귀

; 좀 낫지만, 아직 우수하지는 않다.(defn recur-fibo [n]

(letfn [(fib[current next n](if (zero? n)

current(recur next (+ current next) (dec n))))]

(fib 0 1 n))

1. 함수형 프로그래밍의 개념2. 어떻게 연산을 지연시킬까p156

1. 재귀2. 꼬리 재귀

3. recur를 이용한 자체 재귀4. 지연 시퀀스5. 시퀀스의 실현6. 머리를 쓰지 않기

recur를 이용한 자체 재귀

; 좀 낫지만, 아직 우수하지는 않다.(defn recur-fibo [n]

(letfn [(fib[current next n](if (zero? n)

current(recur next (+ current next) (dec n))))]

(fib 0 1 n))

1. 함수형 프로그래밍의 개념2. 어떻게 연산을 지연시킬까p157

1. 재귀2. 꼬리 재귀3. recur를 이용한 자체 재귀

4. 지연 시퀀스5. 시퀀스의 실현6. 머리를 쓰지 않기

지연 시퀀스

lazy-seq라는 메크로를 이용해 만든다. lazy-seq는 그 body 부분이 꼭 필요할 때만 실행되게 만든다.

1. 함수형 프로그래밍의 개념2. 어떻게 연산을 지연시킬까p157

1. 재귀2. 꼬리 재귀3. recur를 이용한 자체 재귀

4. 지연 시퀀스5. 시퀀스의 실현6. 머리를 쓰지 않기

지연 시퀀스

(defn lazy-seq-fibo([]

(concat [0 1] (lazy-seq-fibo 0 1)))([a b]

(let [n (+ a b)](lazy-seq

(cons n (lazy-seq-fibo b n))))))

빈 벡터가 들어올 경우, 기본값인 [0 1]과 나머지 계산된 값들을 이어붙인 값을 반환

1. 함수형 프로그래밍의 개념2. 어떻게 연산을 지연시킬까p157

1. 재귀2. 꼬리 재귀3. recur를 이용한 자체 재귀

4. 지연 시퀀스5. 시퀀스의 실현6. 머리를 쓰지 않기

지연 시퀀스

(defn lazy-seq-fibo([]

(concat [0 1] (lazy-seq-fibo 0 1)))([a b]

(let [n (+ a b)](lazy-seq

(cons n (lazy-seq-fibo b n))))))

받은 인자 두개로 다음 값인 n을 계계산한다.

1. 함수형 프로그래밍의 개념2. 어떻게 연산을 지연시킬까p157

1. 재귀2. 꼬리 재귀3. recur를 이용한 자체 재귀

4. 지연 시퀀스5. 시퀀스의 실현6. 머리를 쓰지 않기

지연 시퀀스

(defn lazy-seq-fibo([]

(concat [0 1] (lazy-seq-fibo 0 1)))([a b]

(let [n (+ a b)](lazy-seq

(cons n (lazy-seq-fibo b n))))))

n과 다음에 이어질 값들을 리스트로 만든다.

1. 함수형 프로그래밍의 개념2. 어떻게 연산을 지연시킬까p157

1. 재귀2. 꼬리 재귀3. recur를 이용한 자체 재귀

4. 지연 시퀀스5. 시퀀스의 실현6. 머리를 쓰지 않기

지연 시퀀스

(defn lazy-seq-fibo([]

(concat [0 1] (lazy-seq-fibo 0 1)))([a b]

(let [n (+ a b)](lazy-seq

(cons n (lazy-seq-fibo b n))))))

이 줄이 없으면 다음줄에 대한 재귀적 호출이 바로 일어난다. 스택 오버플로우가 발생재귀적인 부분을 lazy-seq로 감싸서 재귀적 호출을 지연해야 한다.

1. 함수형 프로그래밍의 개념2. 어떻게 연산을 지연시킬까p157

1. 재귀2. 꼬리 재귀3. recur를 이용한 자체 재귀

4. 지연 시퀀스5. 시퀀스의 실현6. 머리를 쓰지 않기

지연 시퀀스

(defn fibo [](map first (iterate (fn [[a b]] [b (+ a b)]) [0 1])))

(def lots-o-fibs (take 1000000000 (fibo)))

(nth lots-o-fibs 100)-> 354224848179261915075

1. 함수형 프로그래밍의 개념2. 어떻게 연산을 지연시킬까p157

1. 재귀2. 꼬리 재귀3. recur를 이용한 자체 재귀

4. 지연 시퀀스5. 시퀀스의 실현6. 머리를 쓰지 않기

지연 시퀀스

길이가 가변적이거나 거대한 시퀀스를 다룬다면 지연 시퀀스를 사용하는것이 바람직하다.

1. 함수형 프로그래밍의 개념2. 어떻게 연산을 지연시킬까p160

1. 재귀2. 꼬리 재귀3. recur를 이용한 자체 재귀4. 지연 시퀀스

5. 시퀀스의 실현6. 머리를 쓰지 않기

시퀀스의 실현

지연 시퀀스는 시퀀스가 ‘실현(realization)’될 때, 즉 시퀀스의 일부가 메모리에서 실제로 생성될 때만 자원을 소모한다.

1. 함수형 프로그래밍의 개념2. 어떻게 연산을 지연시킬까p160

1. 재귀2. 꼬리 재귀3. recur를 이용한 자체 재귀4. 지연 시퀀스

5. 시퀀스의 실현6. 머리를 쓰지 않기

시퀀스의 실현

(defn fibo [](map first (iterate (fn [[a b]] [b (+ a b)]) [0 1])))

(def lots-o-fibs (take 1000000000 (fibo)))

(nth lots-o-fibs 100)-> 354224848179261915075

1. 함수형 프로그래밍의 개념2. 어떻게 연산을 지연시킬까p160

1. 재귀2. 꼬리 재귀3. recur를 이용한 자체 재귀4. 지연 시퀀스

5. 시퀀스의 실현6. 머리를 쓰지 않기

시퀀스의 실현

꼭 필요한 부분만 필요한 때에 실현하기 때문에, 프로그래머는 시퀀스의 크기에 신경 쓸 필요가 없다.

1. 함수형 프로그래밍의 개념2. 어떻게 연산을 지연시킬까p161

1. 재귀2. 꼬리 재귀3. recur를 이용한 자체 재귀4. 지연 시퀀스5. 시퀀스의 실현

6. 머리를 쓰지 않기

머리를 쓰지 않기

의도하지 않게 시퀀스의 일부에 대한레퍼런스를 계속 유지한다면, 지연 시퀀스의 장점을 활용하지 못한다.

필요 없는 계산을 한다.

1. 함수형 프로그래밍의 개념2. 어떻게 연산을 지연시킬까3. 더욱 게을러지기4. 다시 재귀로

p162

더욱 게을러지기무언가를 직접 해결하려고 하기보다는, 기존 함수와 시퀀스 라이브러리를조합하면 더 간단하고 범용적인 솔루션을 만들어 낼 수 있다.

1. 함수형 프로그래밍의 개념2. 어떻게 연산을 지연시킬까3. 더욱 게을러지기4. 다시 재귀로

p168

(defn count-heads-pairs [coll](loop [cnt 0 coll1 coll]

(if (empty? coll1)cnt(recur (if (= :h (first coll1) (second coll1))

(inc cnt)cnt)

(rest coll1)))))

1. 함수형 프로그래밍의 개념2. 어떻게 연산을 지연시킬까3. 더욱 게을러지기4. 다시 재귀로

p168

(def count-if (comp count filter))

(defncount-runs [n pred coll](count-if #(every? pred %)

(partition n 1 coll)))

(defn count-heads-pairs (partial count-runs 2 #(= % :h)))

1. 함수형 프로그래밍의 개념2. 어떻게 연산을 지연시킬까3. 더욱 게을러지기4. 다시 재귀로

p170

1. 상호 재귀2. 상호 재귀를 재귀로 바꾸기3. 트램폴린을 이용한 상호 재귀4. 재귀를 평가 지연으로 바꾸기5. 메모이제이션을 이용해 재귀 호출을

줄이기

상호 재귀두 개 이상의 함수가 서로를 호출하면서 생겨난다. 인자 크기에 비례해서 스택을 소모해결 방법

상호 재귀를 재귀로 바꾸기트램폴린을 이용한 상호 재귀재귀를 평가 지연으로 바꾸기메모이제이션을 이용해 재귀 호출을 줄이기

1. 함수형 프로그래밍의 개념2. 어떻게 연산을 지연시킬까3. 더욱 게을러지기4. 다시 재귀로

p170

1. 상호 재귀2. 상호 재귀를 재귀로 바꾸기3. 트램폴린을 이용한 상호 재귀4. 재귀를 평가 지연으로 바꾸기5. 메모이제이션을 이용해 재귀 호출을

줄이기

상호 재귀(declare my-odd? my-even?)

(defn my-odd? [n](if (= n 0)

false(my-even? (dec n))))

(defn my-even? [n](if (= n 0)

true(my-odd? (dec n))))

1. 함수형 프로그래밍의 개념2. 어떻게 연산을 지연시킬까3. 더욱 게을러지기4. 다시 재귀로

p170

1. 상호 재귀2. 상호 재귀를 재귀로 바꾸기3. 트램폴린을 이용한 상호 재귀4. 재귀를 평가 지연으로 바꾸기5. 메모이제이션을 이용해 재귀 호출을

줄이기

상호 재귀(declare my-odd? my-even?)(defn my-odd? [n]

(if (= n 0)false(my-even? (dec n))))

(defn my-even? [n](if (= n 0)

true(my-odd? (dec n))))

1. 함수형 프로그래밍의 개념2. 어떻게 연산을 지연시킬까3. 더욱 게을러지기4. 다시 재귀로

p170

1. 상호 재귀2. 상호 재귀를 재귀로 바꾸기3. 트램폴린을 이용한 상호 재귀4. 재귀를 평가 지연으로 바꾸기5. 메모이제이션을 이용해 재귀 호출을

줄이기

상호 재귀(declare my-odd? my-even?)(defn my-odd? [n]

(if (= n 0)false(my-even? (dec n))))

(defn my-even? [n](if (= n 0)

true(my-odd? (dec n))))

1. 함수형 프로그래밍의 개념2. 어떻게 연산을 지연시킬까3. 더욱 게을러지기4. 다시 재귀로

p171

1. 상호 재귀

2. 상호재귀를재귀로바꾸기3. 트램폴린을 이용한 상호 재귀4. 재귀를 평가 지연으로 바꾸기5. 메모이제이션을 이용해 재귀 호출을

줄이기

상호 재귀를 재귀로 바꾸기(defn parity [n]

(loop [n n par 0](if (= n 0)

par(recur (dec n) (- 1 par)))))

(defn my-even? [n] (= 0 (parity n)))(defn my-odd? [n] (= 1 (parity n)))

1. 함수형 프로그래밍의 개념2. 어떻게 연산을 지연시킬까3. 더욱 게을러지기4. 다시 재귀로

p172

1. 상호 재귀2. 상호 재귀를 재귀로 바꾸기

3. 트램폴린을이용한상호재귀4. 재귀를 평가 지연으로 바꾸기5. 메모이제이션을 이용해 재귀 호출을

줄이기

트램폴린을 이용한 상호 재귀

함수를 ‘구현’하는 사람이 recur를 이용해 재귀를 선언하는 대신에 함수를‘호출’ 하는 쪽에서 recur를 통해 재귀적으로 함수를 호출할 수 있게 해줌

1. 함수형 프로그래밍의 개념2. 어떻게 연산을 지연시킬까3. 더욱 게을러지기4. 다시 재귀로

p172

1. 상호 재귀2. 상호 재귀를 재귀로 바꾸기

3. 트램폴린을이용한상호재귀4. 재귀를 평가 지연으로 바꾸기5. 메모이제이션을 이용해 재귀 호출을

줄이기

트램폴린을 이용한 상호 재귀(declare my-odd? my-even?)(defn my-odd? [n]

(if (= n 0)false#(my-even? (dec n))))

(defn my-even? [n](if (=n 0)

true#(my-odd? (dec n))))

(trampline my-even? 1000000)

익명 함수를 반환 하게 함

1. 함수형 프로그래밍의 개념2. 어떻게 연산을 지연시킬까3. 더욱 게을러지기4. 다시 재귀로

p174

1. 상호 재귀2. 상호 재귀를 재귀로 바꾸기3. 트램폴린을 이용한 상호 재귀

4. 재귀를평가지연으로바꾸기5. 메모이제이션을 이용해 재귀 호출을

줄이기

재귀를 평가 지연으로 바꾸기시퀀스를 만들어 내는 재귀를 없애려면, 그 부분을 lazy-seq로 감싼다.

1. 함수형 프로그래밍의 개념2. 어떻게 연산을 지연시킬까3. 더욱 게을러지기4. 다시 재귀로

p174

1. 상호 재귀2. 상호 재귀를 재귀로 바꾸기3. 트램폴린을 이용한 상호 재귀

4. 재귀를평가지연으로바꾸기5. 메모이제이션을 이용해 재귀 호출을

줄이기

재귀를 평가 지연으로 바꾸기(defn coll-or-scalar [x & _]

(if (coll? X):collection:scalar))

(defmulti replace-symbol coll-or-scalar)

(defmethod replace-symbol :collection [coll oldsym newsym](lazy-seq

(when (seq coll)(cons (replace-symbol (first coll) oldsym newsym)

(replace-symbol (rest coll) oldsym newsym)))))

(defmethod replace-symbol :scalar [obj oldsym newsym](if (= obj oldsym) newsym obj))

1. 함수형 프로그래밍의 개념2. 어떻게 연산을 지연시킬까3. 더욱 게을러지기4. 다시 재귀로

p177

1. 상호 재귀2. 상호 재귀를 재귀로 바꾸기3. 트램폴린을 이용한 상호 재귀4. 재귀를 평가 지연으로 바꾸기

5. 메모이제이션을 이용해재귀 호출을 줄이기

메모이제이션을 이용해 재귀호출을 줄이기

함수가 예전의 계산한 결과를 캐싱하여 공간을 소모하는 대신에 계산 속도를 빠르게 만듬

1. 함수형 프로그래밍의 개념2. 어떻게 연산을 지연시킬까3. 더욱 게을러지기4. 다시 재귀로

p177

1. 상호 재귀2. 상호 재귀를 재귀로 바꾸기3. 트램폴린을 이용한 상호 재귀4. 재귀를 평가 지연으로 바꾸기

5. 메모이제이션을 이용해재귀 호출을 줄이기

메모이제이션을 이용해 재귀호출을 줄이기(declare m f)(defn m [n]

(if (zero? n)0(- n (f (m (dec n))))))

(defn f [n](if (zero? n)

1(- n (m (f (dec n))))))

(def m (memoize m))(def f (memoize f))