(loop (print (eval (read))))

;;닭집을 차리기 위한 여정

구조분해

클로져 시작하기 책을 보다가

번역이 구조분해라구 된 Destructuring 를 같이 토의도 해보고 했다. 이거 꽤 많이 씀.

전형적인 되도는 프로세스를 만드는 함수를 짜보자.

1
2
3
4
5
6
7
8
9
10
11
12
13
;; 구조분해 없이
(defn foldr [f init coll]
(if (empty? coll)
init
(f (first coll)
(foldr f init (rest coll)))))
;; 구조분해 써서
(defn foldr* [f init coll]
(if (empty? coll)
init
(let [[h & t] coll]
(f h (foldr f init t)))))

reduce 함수와 조금 다른 옛 이름의 foldr 함수를 구현해 보았다. (let [[h & t] coll] ... 부분이 구조 분해가 일어나는 부분.

기본적으로는 패턴매칭을 이용하고 있으므러 다른 언어로도 구현해보자

스킴의 하나인 racket은 정신나간 매크로확장을 많이 하는 동네라서 찾아보면 온갖 매크로가 다 튀어나온다.

스킴으로는 클로져의 경우와 반대로 이름이 reducefoldl 을 구현해보자.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
;; #lang racket
;; 걍 안쓰고 했을때
(define (reduce f init coll)
(if (null? coll)
init
(f (reduce f init (cdr coll))
(car coll))))
;; match-let 매크로 사용
(define (reduce* f init coll)
(if (null? coll)
init
(match-let ([(list h t ...) coll])
(f (reduce* f init t) h))))
;; match 매크로사용
(define (reduce** f init coll)
(match coll
['() init]
[(list h t ...)
(f (reduce** f init t) h)]))
;; define/match 매크로 사용 - 함수구현부 패턴매칭
(define/match (reduce*** f init coll)
[(f init '()) init]
[(f init (list h t ...))
(f (reduce*** f init t) h)])

결국 함수선언부 패턴매칭까지 오게 되는데 라켓에는 뭔가 뭘 좋아할지 몰라서 다 준비했다는 식으러 문법확장이 너무 지나치게 많이 일어나는 것 같은 감이 있다.

덤으러 이런건 자바스크립트에서도 된다.

1
2
3
4
5
6
7
8
function foldr(f, init, coll) {
if( coll.length == 0 ) {
return init;
} else {
let [h, ...t] = coll;
return f( h, foldr(f, init, t));
}
}

생각해보면 이런거 하기 가장 좋은 플랫폼은 하스켈 아닌가?