2009. 12. 10.

Remote에 있는 Lisp 구현에 접근해서 개발하기..

준비물

1. 로컬머신
Emacs + Slime

2. 원격머신
SSH , 리습구현

작업

1. 일단 Slime은 로컬 원격  버전을 맞추어서 모두 다운 받는다.
2. 원격 머신에서 다운 받은 Slime의 swank.asd를 적당한 위치(여기에서는 ~/systems/ )에 복사하거나 링크를 만들어 놓는다.
3. 원격머신에서 .sbclrc( SBCL을 쓴다고 가정)을 생성하고 내용을 다음과 같이 만든다.
(require :asdf)
(push "/path/to/~systems/" asdf:*central-registry*)
4. 이제 SBCL에서 다음과 같이 실행시킨다.
(require :swank)
(swank:create-server :port 4005)
5. ssh를 이용 리모트 머신과 로컬 머신의 포트를 서로 맞춘다.
ssh -L4005:127.0.0.1:4005 username@host
6. 클라이언트 머신에서 emacs의 .emacs파일에서 slime을 로딩한다.
(require 'slime)
7. 이제 M-x slime-connect를 해서 서버는 127.0.0.1 로하고 포트를 4005로 맞추면 이제부터 리모트 머신의 swank를 통해 lisp evaluation을 할 수 있다.

8. 추가로 로컬에서 lisp사용시 항상 해당 서버쪽에 맞게끔 이름을 넣고 싶다면 다음과 같은 내용을 .emacs에 넣는다.

;; remote <-> local translate
(setf slime-translate-to-lisp-filename-function
      (lambda (file-name)
        (subseq file-name (length "/ssh:siabard@192.168.10.42:")))
      slime-translate-from-lisp-filename-function
      (lambda (file-name)
        (concat "/ssh:siabard@192.168.10.42:" file-name)))



2009. 12. 2.

Clojure 사용소감

지극히 주관적인 소감입니다.

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..



Clojure 의외로 불편하다..

일단 예전에는 List 하나로만 확인했던 작업이 vector, seq, set 으로 나눠지다보니 상당히 혼란스럽다. =.=
특히나 append 같이 명령어가 바뀐 것은 정말 헤메기 딱좋다. (concat 으로 바뀌었다.)

cond, let의 문법 변화는 좋은지 나쁜지는 모르겠지만... 데이터/코드적 순결성에서는 안좋은 느낌.. 나름 vector 로 처리했다고 자부하는 것 같긴한데.. 글쎄??

PAIP 1장 시작이 어느 정도 진행되기는 하니까 계속 지켜볼 생각임..