지극히 주관적인 소감입니다.
PAIP(Paradigms of Artificial Intelligence Programming)를 공부하는 중인데 On Lisp이랑 Practical Common Lisp을 clojure 로 공부하는 사람들의 기사를 보고, 하는 김에 리습이랑 클로져를 같이 해보자 하고 시작했습니다.
이 책의 모든 소스코드는 Common Lisp 기준이라서 그래도 같은 계열인데 쉽겠지하고 붙었다가 어려움을 겪고 있습니다.
아직은 극 초반이기는 한데.. Common Lisp에서 익숙한 개념을 Clojure에서는 다르게 봐야하는 부분이 조금씩 있습니다.
1. list보다는 vector
일단 함수의 인자부터 Common lisp은 list 인데 비해, clojure는 vector라는 개념을 사용합니다.
이런 이유로 몇몇 special form의 규칙도 살짝 바뀐게 있습니다.
cond, let이 대표적인데 익숙해지기전에는 혼동을 일으키기 쉽습니다.
2. assoc 대신 set
리습코드를 많이 보면 리스트에서 특정 키값으로 찾는 assoc이 있습니다. 이런 방식 대신 clojure에서는 set이라는 데이터구조를 직접다루게 합니다. 그러다보니 구현상에서 ((..) (..) .. ) 식으로 구현했던 많은 부분을 clojure에서는 { key val ... } 식으로 풀어쓰는 경우가 많게 됩니다. 대신 rassoc 를 대신할 만한 것을 찾기가 어렵습니다.
3. 데이터 값을 함부로 바꾸기 어렵게 되었습니다.
기본적으로 clojure 함수는 java의 Runnable 인터페이스를 구현했고, 각 데이터는 이런 스레드상에서 변경이 된다고 보는 것 같습니다. 그렇기때문에 어느 정도 synchronized 같은 방법을 동원하는 것 같습니다. dosync 같은 것을 사용해서 값을 변경할 수는 있습니다만.. 어떤 데이터 형인지에 따라서 그 값을 바꿀 수 있는 방법도 다릅니다. ref, atom, agent같은 개념을 사용해서 스레드에 안전한 데이터를 사용하도록 합니다.
4. 재귀가 그리 만만하지 않습니다.
기본적으로 재귀호출은 같습니다만 lazy evaluation이나 tail call optimization같은 것을 사용하려면 여러 면에서 신경써야합니다. 사실 Common Lisp은 tail call optimization이 그닥 많이 구현되지도 않았고, lazy evaluation같은 것은 기본 내용에 포함되지 않는 경우가 많았는데.. clojure는 lazy evalution을 가급적 잘 활용하도록 강조하고 있고, tail call optimization을 지원하기위해 recur나 trampoline 같은 독특한 구조도 지원합니다. (사실 JVM이 tail call optimization을 지원안하는게 가장 큰 이유겠지요)
이런 식입니다. 앞으로 조금씩 더 파나가다보면 더 많은 것이 나오겠지요.. 어쩌면 어색했던 것이 더 편할지도 모르겠습니다.
아무튼 재미있는 Lisp구현임에는 틀림없는 것 같네요..
--
새로움을 느끼기에 삶은 즐겁다..
모험가 아돌 크리스틴을 꿈꾸며..
Sia..

PAIP(Paradigms of Artificial Intelligence Programming)를 공부하는 중인데 On Lisp이랑 Practical Common Lisp을 clojure 로 공부하는 사람들의 기사를 보고, 하는 김에 리습이랑 클로져를 같이 해보자 하고 시작했습니다.
이 책의 모든 소스코드는 Common Lisp 기준이라서 그래도 같은 계열인데 쉽겠지하고 붙었다가 어려움을 겪고 있습니다.
아직은 극 초반이기는 한데.. Common Lisp에서 익숙한 개념을 Clojure에서는 다르게 봐야하는 부분이 조금씩 있습니다.
1. list보다는 vector
일단 함수의 인자부터 Common lisp은 list 인데 비해, clojure는 vector라는 개념을 사용합니다.
이런 이유로 몇몇 special form의 규칙도 살짝 바뀐게 있습니다.
cond, let이 대표적인데 익숙해지기전에는 혼동을 일으키기 쉽습니다.
2. assoc 대신 set
리습코드를 많이 보면 리스트에서 특정 키값으로 찾는 assoc이 있습니다. 이런 방식 대신 clojure에서는 set이라는 데이터구조를 직접다루게 합니다. 그러다보니 구현상에서 ((..) (..) .. ) 식으로 구현했던 많은 부분을 clojure에서는 { key val ... } 식으로 풀어쓰는 경우가 많게 됩니다. 대신 rassoc 를 대신할 만한 것을 찾기가 어렵습니다.
3. 데이터 값을 함부로 바꾸기 어렵게 되었습니다.
기본적으로 clojure 함수는 java의 Runnable 인터페이스를 구현했고, 각 데이터는 이런 스레드상에서 변경이 된다고 보는 것 같습니다. 그렇기때문에 어느 정도 synchronized 같은 방법을 동원하는 것 같습니다. dosync 같은 것을 사용해서 값을 변경할 수는 있습니다만.. 어떤 데이터 형인지에 따라서 그 값을 바꿀 수 있는 방법도 다릅니다. ref, atom, agent같은 개념을 사용해서 스레드에 안전한 데이터를 사용하도록 합니다.
4. 재귀가 그리 만만하지 않습니다.
기본적으로 재귀호출은 같습니다만 lazy evaluation이나 tail call optimization같은 것을 사용하려면 여러 면에서 신경써야합니다. 사실 Common Lisp은 tail call optimization이 그닥 많이 구현되지도 않았고, lazy evaluation같은 것은 기본 내용에 포함되지 않는 경우가 많았는데.. clojure는 lazy evalution을 가급적 잘 활용하도록 강조하고 있고, tail call optimization을 지원하기위해 recur나 trampoline 같은 독특한 구조도 지원합니다. (사실 JVM이 tail call optimization을 지원안하는게 가장 큰 이유겠지요)
이런 식입니다. 앞으로 조금씩 더 파나가다보면 더 많은 것이 나오겠지요.. 어쩌면 어색했던 것이 더 편할지도 모르겠습니다.
아무튼 재미있는 Lisp구현임에는 틀림없는 것 같네요..
--
새로움을 느끼기에 삶은 즐겁다..
모험가 아돌 크리스틴을 꿈꾸며..
Sia..

댓글 없음:
댓글 쓰기