"리습은 그것을 마침내 손에 넣게 되었을 때 경험하게 되는 심오한 깨달음을 위해서라도 배울 가치가 있다. 리습을 이용할 일이 그렇게 많지 않다고 할지라도 그 경험은 그 자체만으로도 당신을 훨씬 훌륭한 프로그래머로 만들어 줄 것이다." - 에릭 레이먼드 (Eric Raymond)


제가 아는 선배가 송재경 (바람의 나라, 리지니 만드신 분) 씨와 인터뷰를 할 일이 있었는 데 그 분이 하신 말씀 중에

"프로그램은 어떠한 언어로 짜는 것이 중요한 것이 아니다. 가장 중요한 것은 전산적인 마인드를 소유하는 것이다"

라는 이야기를 들었다고 합니다. 상당히 많은 시간이 지났지만 이 이야기가 가지고 있는 의미는 아직까지도 도움이 됩니다. 저 또한 후학들을 만나면 이와 같은 이야기를 많이 합니다.

왜 리습을 공부해야 하는가? 전산적인 마인드를 소유하는데 도움이 되는 연습을 가장 열심히 할 수 있는 언어였다고 자신할 수가 있습니다.

저는 예전에도 리습을 공부하였고, 지금도 공부중이고 앞으로도 공부할 것입니다. 조금만 떨어지면 멀어져 버리는 전산적인 마인드를 붙잡기 위해서 입니다. (요즘은 리습 방언인 클로져에 빠져 있습니다)


lein 을 이용한 프로젝트 생성시 요즘 clojure 버젼이 1.4.0 이 기본인 것처럼 만들어 집니다. 아무 생각 없이 slime 을 연결해서 코딩을 시작하면 무엇인지 이상한 기분이 들기 시작합니다. 바로

doc

함수 입니다. doc 함수가 동작을 안합니다. "1.2.1" 버젼에서는 제대로 동작했는데 갑자기 동작안하기 시작합니다. 정확히는 "1.3.x" 와 "1.4.0" 에서 동작을 안합니다.

REPL 상에서

user> (use 'clojure.repl)


만 해주면 그 다음부터 사용이 됩니다.
저번 포스트 에서 Clojure 와 Emacs 와 Slime 을 연동 시키는 방법을 했다면, 이제 실제 클로져 코드를 짜야 하는 일이 생길 것입니다. 그런데 전역으로 환경을 세팅하는 것이 아니기 때문에 다른 클로져 라이브러리를 포함 시키는 것이 어려울 것 같습니다. 특히 clojure-contrib 같은 거의 필수 라이브러리는

lein 으로 만들어준 프로젝트의 project.clj 를 열어줍니다.

$ lein new test-project
$ cd test-project
$ emacs project.clj


다음 과 같이

                 [org.clojure/clojure-contrib "1.2.0"]


의 내용을 :dependencies 에 추가해 줍니다.


아래에 붙어 있는 congomongo 는 무시하세요.

$ lein deps


를 실행해 주면 clojure-contrib 를 다운 받아서 프로젝트 환경에 추가해 줍니다.
이제 Emacs 상에서 Clojure 랑 Slime 을 연동시켜서 원하는 코드를 만들어 주면 됩니다.

M-x clojure-jack-in


In console 'Terminal'

$ sudo apt-get install clojure
$ sudo apt-get install leiningen
$ sudo apt-get install slime

install clojure-mode

$ cd ~/.emacs.d
$ git clone git://github.com/technomancy/clojure-mode.git

append to dot-emacs

$ emacs ~/.emacs

add followings below

    (add-to-list 'load-path "~/.emacs.d/clojure-mode/")
    (require 'clojure-mode)

install swank-clojure

$ lein plugin install swank-clojure 1.3.3

make clojure test project
   
$ mkdir ~/tmp
$ cd ~/tmp
$ lein new test-project
$ cd test-project
$ lein deps

invoking slime for clojure
   
$ emacs project.clj

in Emacs

M-x clojure-jack-in

enjoy yourself!!

for Korean

클로져를 Emacs 랑 연동하는 방식이 여러가지가 존재합니다. 이거 저거 다 해봤는데 잘 안되더군요. 개인적으로 apt-get 을 이용해서 개발환경 관리하는 것을 즐겨하는 편인데 잘 뒤져봐도 이것에 관한 내용들이 없더군요. 그래서 정리해 봤습니다.

터미널 창에서 다음 과 같이 입력해 줍니다. emacs 는 이미 설치가 되어 있다고 가정합니다.

$ sudo apt-get install clojure
$ sudo apt-get install leiningen
$ sudo apt-get install slime

클로져 모드 (Clojure-mode) 를 설치해줍니다. git 는 이미 설치가 되어 있다고 가정합니다.

$ cd ~/.emacs.d
$ git clone git://github.com/technomancy/clojure-mode.git

.emacs 를 열어서

$ emacs ~/.emacs

다음과 같은 내용을 추가해 줍니다. 이는 클로져 모드를 쓸 수 있게 해주는 것입니다.

    (add-to-list 'load-path "~/.emacs.d/clojure-mode/")
    (require 'clojure-mode)

 스웽크 클로져(swank-clojure)를 설치해줍니다. slime 이 연결하는 대상이 될 것입니다.

$ lein plugin install swank-clojure 1.3.3

테스트용으로 clojure 프로젝트를 만들어 봅니다.
   
$ mkdir ~/tmp
$ cd ~/tmp
$ lein new test-project
$ cd test-project
$ lein deps

실제로 slime 하고 연동해 보기로 합니다.
   
$ emacs project.clj


clj 파일을 열어서 Emacs 상에서 다음과 같이 명령을 입력해 주면

M-x clojure-jack-in

바로 Slime 하고 연동되서 뜨는 것을 확인하실 수 있습니다.
 


Closure 라고 들어 보셨는지요. 최근에 차기 Java 버젼에 포함되기를 많은 사람이 희망하였다가 무산 되서 실망의 글로 자바 관련 게시판들이 도배가 됐다고 합니다. 자 그러면 대체 클로져 (Closure) 란 무엇인지 위키피디아의 내용을 보기로 하겠습니다.


http://en.wikipedia.org/wiki/Closure_%28computer_science%29


어려운 내용들로 도배가 되어 있습니다. 쭈욱 살펴보자면 함수를 리턴하는 언어들에게서 흔히 찾아 볼 수 있는 개념이고요. Anonymous Function 하고 착각하면 안된다고 쓰여져 있습니다. 즉 'function value' 개념이라는 식으로 언급이 되어 있습니다.


가장 쉽게 설명하자면 '지역 변수' 가 코드가 쓰여질 때의 값으로 지정되는 것이 아니라 '클로져'가 생성될 때 그 '값'에 접근이 가능하다? 라는 식으로 쓰여질 수가 있겠습니다. 


이러니 저러니 해도 여러가지 형태가 결부되어 있지만 , 


1. 함수가 리턴 되어야 하고

2. variable 이 관련 있어야 한다. (이것이 관련 없으면 클로져가 아니다)



아무래도 정말 쉽게 설명 하자면 예제 케이스를 가지고 설명하는 것이 가장 쉬울 것 같습니다.

EDITED. 2012 - 09 - 04

아무래도 Lisp 의 방언인 Clojure 로 설명을 하니 못 알아먹겠다는 원성이 자자해서 위키 페이지에 나와 있는 자바스크립트를 예로 설명드리겠습니다. 

function derivative(f, dx) {
  return function (x) {
    return (f(x + dx) - f(x)) / dx;
  };
}

함수 derivative 는 f 라는 함수와 dx 라는 변수를 입력받아서 , x 라는 인자를 받아서 처리하는 함수를 리턴하는 함수 입니다. 

리턴되는 function(x) 는 derivative 에서 넘겨받은 f 와 dx 에 영향을 받을 수밖에 없겠지요? 즉 리턴되는 function (x) 는 어찌 되었든 간에 derivative 에서 넘겨 받는  f 와 dx 에 의존해서 구현이 달라집니다. 이때 function(x) 가 derivative 의 인자인 f 와 dx 와 클로져 (Closure) 다 라고 합니다. 



클로져 (Clojure) 로 만든 Closure 의 예입니다. (발음이 같은 이유는 바로 관련이 있기 때문입니다)  함수를 세분해서 설명하겠습니다.


user> (defn make-greeter [greeting-prefix]
        (fn [username] (str greeting-prefix ", " username)))
#'user/make-greeter


make-greeter 라는 함수를 리턴하는 함수입니다. greeting-prefix 값을 받아서 그 값을 이용하는 함수를 리턴합니다.
defn 은 함수 선언을 지정하는 함수이고요. fn 은 내부 함수 선언용입니다. (str greeting-prefix ", " username) 이 부분 greeting-prefix 랑 " , " username 을 합쳐서 리턴하는 명령 입니다.

user> (def hello-greeting (make-greeter "Hello"))
#'user/hello-greeting

make-greeter 에 "Hello" (greeting-prefix 값이 "Hello" 가 됩니다) 를 인자로 넘겨서 반환되는 함수를 hello-greeting 으로 지정해 줍니다.

user> (hello-greeting "crazia")
"Hello, crazia"
user>

완성된 함수를 테스트 해봅니다.  greeting-prefix 값이 변함에 따라서 전혀 다른 함수가 만들어 집니다. "Hello" 대신 "Hi " 를 넣어서 리턴되는 함수는 또 다른 함수가 되겠지요? 자 이때!!!

make-greeter 에 의해서 리턴되는 함수가 greeting-prefix 값 에 대한  closure 다

이라고 합니다.


새로운 것을 좋아하는 후배가 책까지 사주면서 보라고 해서 결국 Clojure를 설치하기로 했습니다.

Mac port 이용해서 Clojure 설치 하기

가장 쉬운 방법으로는 mac port 를 이용하는 방법이 있습니다.

sudo port install clojure


하면 너무나 손쉽게 설치됩니다. 하나 이러한 방법을 쓰면 나중에 Emacs 나 Slime 과 연동 설치할 때 귀찮아 지기 때문에 수동 설치를 하려고 마음을 먹었습니다.

Clojure 수동 설치 하기

참조 사이트: http://riddell.us/ClojureOnUbuntu.html

위에 링크한 사이트는 제가 여러모로 도움을 받는 사이트 입니다. 역시나 클로져도 우분투에 편하게 설치하는 방법이 잘 정리되어 있더군요. "그냥 사이트 보세요" 만큼 형편없는 도움말은 없겠지요. 그래서 거기 나와 있는 내용을 조금 제 형편에 맞게 정리해 볼까 합니다.

기본적으로 osx 는 자바가 설치되어 있습니다. 따로 설치해줄 필요 없으니 자바는 생략하고요. git 역시 설치되어 있다고 가정하지요. 제가 어떻게 설치했는지 기억이 안나는 군요..Maven 은 설치해준 기억이 없는데 설치되어 있는것을 보니 어영 부영 설치되어 있는 것 같습니다.

Ant 설치
 Ant 는 아마 기본으로 설치가 안되어 있을 것입니다.

~$ sudo port install ant


Clojure 설치

최신 버젼을 받아서 컴파일 해서 설치해 주면 됩니다.

~$ mkdir ~/work

~$ cd ~/work

~$ git clone git://github.com/richhickey/clojure.git

~$ cd clojure

~$ ant

~$ mkdir ~/.clojure

~$ cp clojure.jar ~/.clojure


저는 기본적으로 코드 관련 소스들은 work 밑에 저장하기 때문에 work 를 썼습니다. 코드 관련 폴더를 하나씩 만들어서 쓰시는 것을 추천합니다.

Clojure 테스트 하기

~$ cd ~/.clojure

~$ java -cp clojure.jar clojure.lang.Repl

user=> (+ 1 41)

42


Ctrl-d 를 누르면 REPL 을 빠져 나갑니다.

clojure-contrib 설치 하기

clojure-contrib 은 공식적인 클로져 확장 라이브러리 모음집 같은 것입니다.

~$ cd ~/work

~$ git clone git://github.com/richhickey/clojure-contrib.git

~$ cd clojure-contrib

~$ mvn package

~$ cp target/clojure-contrib*.jar ~/.clojure/clojure-contrib.jar


자 이제는 편하게 REPL 로 들어가는 스크립트를 만드는 순서 입니다.

~/.bash_profile 아래쪽에 다음과 같은 내용을 채워 넣습니다.

export CLOJURE_EXT=~/.clojure

PATH=$PATH:~/work/clojure-contrib/launchers/bash

alias clj=clj-env-dir


저장하고 Terminal 창을 종료했다가 다시 열어서 테스트를 해 줍니다.

~$ clj
Clojure 1.2.0-master-SNAPSHOT
user=> (System/getProperty "java.class.path")
"/Users/crazia/.clojure/clojure-contrib.jar:/Users/crazia/.clojure/clojure.jar"
user=>


위처럼 clojure.jar 와 clojure-contrib.jar 의 위치가 표시되면 만사 OK 입니다.

Clojure 와 clojure-contrib 의 업데이트는 굳이 설명할 필요가 없을 듯 하여 생략합니다.

+ Recent posts