[왜 클로저(Clojure)인가?] 2. 클로저(Clojure)의 본질적 우수성

윌슨의 미로 발생기 알고리즘 :

  1. 임의의 좌표를 골라서 방문 표시한다.

  2. 방문하지 않은 임의의 좌표를 고른다 – 만약 없다면 미로 출력

  3. 2에서 고른 좌표에서 출발하여  방문 표시된 위치까지 랜덤 걷기한다 – 랜덤 걷기 중 한 위치를 2번 이상 지난다면, 항상 그 방향을 기억한다.

  4. 랜덤 걷기한 모든 위치를 방문 표시하고, 출구 방향에 따라 벽을 제거한다.

  5. 2로 돌아간다.


아래는 윌슨 알고리즘을 클로저로 구현한 코드이다. (Clojure Programming p.147에서 인용)

 

(defn maze [walls] (let [paths (reduce (fn [index [a b]] (merge-with into index {a [b] b [a]})) {} (map seq walls)) start-loc (rand-nth (keys paths))] (loop [walls walls unvisited (disj (set (keys paths)) start-loc)] (if-let [loc (when-let [s (seq unvisited)] (rand-nth s))] (let [walk (iterate (comp rand-nth paths) loc) steps (zipmap (take-while unvisited walk) (next walk))] (recur (reduce disj walls (map set steps)) (reduce disj unvisited (keys steps)))) walls))))

 

이 코드를 당장 이해할 필요는 없다. 아래는 윌슨의 미로 발생기 알고리즘을 구현한 클로저 코드와 자연어(한글) 기술을 라인별 일대일 매칭 관계를 보여준다.

 

 

클로저 구현 코드

자연어(한글) 기술

1줄

(defn maze  [walls]

X

2줄

(let [paths (reduce (fn [index [a b]]

X

3줄

(merge-with into index {a [b] b [a]}))

X

4줄

{} (map seq walls))

X

5줄

start-loc (rand-nth (keys paths))]

윌슨 1: 임의의 좌표를 골라서

6줄

(loop [walls walls

X

7줄

unvisited (disj (set (keys paths)) start-loc)]

윌슨 1: 방문 표시한다.

8줄

(if-let [loc (when-let [s (seq unvisited)] (rand-nth s))]

윌슨 2: 방문하지 않은 임의의 좌표를 고른다.

9줄

(let [walk (iterate (comp rand-nth paths) loc)

윌슨 3: 랜덤 걷기 수행.

10줄

steps (zipmap (take-while unvisited walk) (next walk))]

윌슨 3: 방문 표시된 위치까지

11줄

(recur (reduce disj walls (map set steps))

윌슨 4: 벽 제거

12줄

(reduce disj unvisited (keys steps))))

윌슨 4: 방문 표시한다.

13줄

 walls))))

윌슨 2: 만약 없다면 미로 출력


위 표에서 X로 표시된 것은 클로저 코드 라인중에서 윌슨의 알고리즘을 자연어(한글)로 표기한 문장에서 표현되지 않은 것을 나타내는데, 단지 전체 클로저 코드 라인 13개 라인중에서 5개 뿐이다.  즉 자연어와 무관하게 프로그래밍 언어 그 자체만을 위한 코드 라인은 5개 뿐이고, 나머지 8개 라인은 자연어의 표현을 그대로 클로저 코드로 표현하고 있는 것이다. 이것은 클로저 코드는 인간의 자연어에 비견되는 수준의 추상화 로 프로그래밍 코드를 만들어 낼 수 있다는 것을 보여준다.

이처럼 클로저는 그 표현력이 매우 뛰어나고 코드의 길이가 매우 짧다. (함수형 언어를 접해본 경험이 없는) 자바나 C++ 프로그래머들이 클로저를 공부하면서 느끼게 되는 것은 ‘어떻게 이렇게 짧은 코드로 그 많은 것을 표현할 수 있지? 도대체 이 코드들에는 버그가 들어설 자리조차 없어 보인다’ 라는 것이다.

클로저의 이러한 특성은 복잡성을 제거하고 단순성을 최대화하는 것에 역점을 두고 프로그래밍 언어 설계시에 언어의 구성에 필요한 패러다임 요소들을 선택했기 때문이다.


http://www.techsuda.com/archives/1909