저는 SLIME과 swank-clojure, clojure-mode 각각을 고유 저장소에서 직접 내려 받아 사용하고 있습니다. 그런데, SLIME이 변경되는 속도는 swank-clojure가 그것을 따라잡는 속도보다 조금 더 빠르고, Clojure의 여러 가지 파격적(?) 문법이 함수형 언어에 '달아' Common Lisp과 '서르 사맛디 아니'하다는 점 때문에 약간의 문제가 생기곤 합니다. 그래서, 지금까지 저장소 버전을 사용하면서 겪었던 문제에 대해 그 해결 방법을 정리해보았습니다.
1. SLIME REPL 버퍼가 멈추는 문제
제일 처음 겪은 심각한 문제는 SLIME의 REPL 버퍼가 멈추는 것이었습니다. 도무지 원인을 알 수가 없었지요. 이리저리 마구잡이로 설정을 변경해가며 테스트 해보다가 결국 알아낸 것이, slime-autodoc-mode가 활성화되어 있을 때 문제가 발생한다는 것이었습니다.
이 문제를 해결하기 위한 방법은 간단합니다. SLIME을 시작하기 전에 slime-autodoc-mode를 비활성화해주면 됩니다.
(setq slime-use-autodoc-mode nil)Common Lisp에선 slime-autodoc-mode가 문제 없이 잘 동작하므로, Clojure와 Common Lisp을 같이 사용하는 경우라면 별도의 함수를 만들어서 상황에 따라 slime-use-autodoc-mode 변수값을 적절히 바꿔주면 됩니다.
그리고, SLIME이 clojure-mode와 연동되기 때문에 clojure-mode에서 slime-autodoc-mode가 활성화될 경우 마찬가지로 SLIME REPL 버퍼가 멈추게 됩니다. 이 문제를 해결하기 위해서는 clojure-mode에 대해 slime-autodoc-mode를 비활성화하는 hook을 추가해줍니다.
(eval-after-load "clojure-mode" '(progn (add-hook 'clojure-mode-hook (lambda () (slime-autodoc-mode 0)))))
또 한 가지, desktop-save-mode를 설정해서 사용하고 있고, Emacs 실행 시 자동으로 다시 열리는 파일 중 clojure 소스 파일이 있다면 여전히 SLIME REPL 버퍼와 clojure 소스 버퍼가 멈추는 문제가 발생합니다. 그러므로, slime-mode에 대해 다음과 같이 hook을 추가해줄 필요가 있습니다. (clojure-mode일 경우에 slime-autodoc-mode를 비활성화하고 그 외의 경우에는 활성화합니다.)
(eval-after-load "slime" '(progn (add-hook 'slime-mode-hook (lambda () (if (eq major-mode 'clojure-mode) (slime-autodoc-mode 0) (slime-autodoc-mode 1)))) (add-hook 'slime-connected-hook (lambda () (if (string= (slime-lisp-implementation-type) "Clojure") (setq slime-use-autodoc-mode nil) (setq slime-use-autodoc-mode t)))))) (eval-after-load "slime-repl" '(progn (add-hook 'slime-repl-mode-hook (lambda () (if (string= (slime-lisp-implementation-type) "Clojure") (progn (setq slime-use-autodoc-mode nil) (slime-autodoc-mode 0)) (progn (setq slime-use-autodoc-mode t) (slime-autodoc-mode 1)))))))
2. Evaluation abort 상황에서 오류 발생하는 문제
SLIME REPL 상에서 일반적인 에러가 발생하면 sldb 버퍼가 뜨는데, 여기서 'Quit to the SLIME top level'을 선택하면 아래와 같은 에러 메시지를 보게 됩니다.
error in process filter: Wrong number of arguments: nil, 0위 상황 외에도 다른 몇몇 상황에서 역시 동일한 에러 메시지를 보게 되는데, 이 문제는 저장소 상의 최신 SLIME 소스에서 swank abort 메시지 인터페이스가 변경되었기 때문에 발생하게 된 것입니다. 변경된 swank abort 메시지 인터페이스는 condition 인자를 하나 필요로 하지만, swank-clojure에선 아무런 인자 없이 abort 메시지만 전달하기 때문에 에러가 발생하는 것이죠. 이 문제를 해결하기 위해선 swank-clojure 쪽 소스를 살짝 손봐야 합니다.
[swank-clojure 폴더]/src/swank/core.clj 파일에서 아래 부분을 모두 찾아,
(:abort)
다음과 같이 수정해줍니다. (물론 이것은 공식적인 해결 방법은 아닙니다. 에러 없이 동작할 수 있도록 임시로 수정해주는 것이죠.)(:abort ~(thread-name (current-thread)))
이 글을 작성하고 있는 시점에서 수정해야 할 부분은 총 5 곳인데, 모두 eval-for-emacs 함수 내부에 있습니다.수정 후 다시 swank-clojure를 구동한 다음 sldb에서 확인해보면 'Quit to the SLIME top level'을 선택했을 때 REPL 상에서 정상적으로 아래와 같은 메시지를 볼 수 있습니다.
; Evaluation aborted on Swank REPL Thread.