Pascal Costanza의 몹시 주관적인 LISP 가이드

http://www.pascalcostanza.de/lisp/guide.html
(v1.3, 3/1/2004)

Copyright © 2002, 2004 Pascal Costanza. All rights reserved. Permission to copy, transmit, and store this work, unmodified and in its entirety, is granted.

You can use this document as an online reference or print it out. All links are represented as explicit URLs that will be retained when printed. Please send any kind of feedback to costanza@web.de.

한국어 번역: 2004/02/09, 조승모


파트 I: 배경

I always wanted to be a lumberjack!
- Monty Python

1. 나는 왜 이 소개글을 쓰고 있는가?


이 부분은 2002년 8월에 쓰여진 것이다. 따라서 기술된 상황은 이제 과거의 것이지만, 원래 느낌을 유지하기 위해서 시제를 바꾸지 않기로 하였다.


내 현 상황은 다음과 같다. 나는 지난 7년간 자바(Java) 프로그래머로서 일해 왔고, 주로 자바를 확장하는 프로젝트들에 참여해 왔다. 이전에는 보통 워쓰(Wirth) 패밀리에 속하는 언어들(주로 Modula-2와 Oberon)을 사용하고 있었으므로, 처음에는 자바가 이런 언어들에 비해 가지는 장점들이 나를 기쁘게 했다.

작년에 나는, 자바 또한 매우 - 사실, 극단적으로 - 제약된 언어라는 것을 깨닫고, 대안들을 알아보기 시작했다. 나는 Feyerabend 프로젝트(http://www.dreamsongs.com/Feyerabend/Feyerabend.html)에 관여했었으므로, Lisp은 자연스럽게 그 대안들 중 하나로 인식되었다. (Feyerabend 프로젝트은 Richard Gabriel에 의해 시작되었는데, 그는 또한 1980년대 초반에 CL(Common Lisp) 표준화를 제안한 사람들 중의 한명이었다.)

여러 가지 좋은 언어들이 있지만 - 예를 들어 (알파벳 순으로) : gbeta, Objective CAML, Python, Ruby - 나는 단번에, Lisp이 어떤 의미로는 이런 모든 언어들의 모체라는 인상을 받았다. 이렇게 말할 수 있는 주된 이유는, Lisp은 코드와 데이터를 단일하게 취급함으로써, 완전한 계산 이론(a complete theory of computation)을 포함하고 있다는 점이다. (이것은 "단순히" Turing-complete한 것보다 더 강력한 것이다. 더 자세한 정보는 아래의 "Lisp의 기술적 배경" 부분을 참고하라.) 이는 Lisp에는 어떠한 (개념적) 제약도 없다는 것을 의미한다: 만일 다른 언어로 어떤 것을 할 수 있다면, Lisp으로도 할 수 있다. 더 나아가, Lisp은 모든 타입(type)을 수행시간에 체크하므로, 정적 타입 시스템에 의해 방해받는 일도 없다.

이런 관찰을 일반화하면 다음과 같이 말할 수 있다: Lisp의 사고방식에서는, 표현력이 프로그래밍 언어에서 유일하게 가장 중요한 요소라고 본다. 다른 어떤 것도, 이런 표현력의 사용에 장해가 되어서는 안된다. 프로그래밍 언어가 그 자신의 세계관을 프로그래머에게 강요해서는 안된다. 프로그래머가 언어를 자신의 필요에 맞게 수정해야지, 그 반대이어서는 안된다.

이는 나에게 아주 매력적이었고, 그래서 나는 Lisp을 선택하기로 했다. 그러나 Lisp을 좀 더 진지하게 들여다 보기에는, 한가지 문제점이 있다: 인터넷에는 내 필요에 맞는 정말 좋은 소개문서가 없었다. (혹은 내가 찾지 못했을 뿐인지도 모르지만.) 물론 몇개의 문서가 존재하지만, 그들은 보통, 너무 저수준으로 초보자에게 프로그래밍 자체를 가르치는 문서이거나, 너무 학술적이어서 이론적으로나 재미있을 주제들을 다루는 문서들이다. 내가 원했던 것은, 개념들을 이해하고 가능한 빨리 작업할 수 있게 하는, 충분한 배경지식을 제공하는 소개문서였다. ("경험있는 프로그래머를 위한 Lisp" 같은 문서랄까.)

그런 것을 찾지 못했으므로, 나는 가능한 자료들을 통해 스스로 해 나갈 수 밖에 없었다. 이에, 내가 찾은 것들을 정리하여 다른 사람들의 작업을 쉽게 하고자 한다.

왜 이 문서가 "몹시 주관적"인가? Lisp은 복잡한 언어, 혹은 언어들의 패밀리이다. Lisp에 대한 "하나의 결정적 가이드" 따위는 있을 수 없다. 여기에 제시하는 것은, 내가 처음에 봤었으면 좋았을 걸, 하고 지금 생각하는 것이다. 다른 사람들은 아마 다른 접근법을 선호할 것이다. 나는 모든 사람을 위한 모든 정보를 제공하는 소개문서를 만들고 싶지는 않다. 내가 원하는 것은 단지 나와 유사한 사람들에게 유용한 정보를 제공하는 것이다. 적어도, 이것은 나한테는 유용했던 자료였고, 따라서 아마도 다른 어떤 사람들에게도 적합할 것이다.

특히, 이것은 "Common Lisp 21일 완성" 등과 같은 문서가 아니다. 실제로 "Common Lisp 경험"에 대한 감을 잡으려면, 당신은 아마도 여기 제공된 것, 혹은 다른 자료들을 여러번 읽어볼 필요가 있을 것이다. (... 하지만 어떤 진짜 언어를 배우기 위해서도, 사실 21일보다는 훨씬 더 걸린다는 사실을 굳이 강조하지는 않아도 될 것이다. 그렇지 않은가? ;)

2. 일반적인 소개

Lisp은 긴 역사를 가지고 있다. 1950년대에 발명되었으며, 그후 수십년에 걸쳐 꾸준히 개발되고 개선되어 왔다. 그 과정에서 여러번, Lisp의 여러 변종들이 나타났고, 따라서 Lisp은 하나의 언어라기보다는 언어들의 패밀리라고 말하는 것이 옳다. (만일, C, C++, Objective C, Java, C# 등을 같은 "유사 C" 언어 패밀리라고 생각한다면, 그와 아마 상당히 유사할 것이다.)

1980년대와 1990년대에 들어, 그 중 두개의 변종들이 유일하게 널리 사용되고 쓸만한 언어로서 정착되었다: Common Lisp (CL)과 스킴(Scheme)이다. 스킴은 1970년대에 Gerald Jay Sussman과 Guy L. Steele에 의해, 객체지향을 이해하고 그것을 Lisp에 결합시키려는 시도의 결과로써 발명되었다. 스킴은 개념적 레벨에서, 객체의 일반화로서의 렉시컬 클로저(lexical closure)와, 함수호출과 메시지전송의 일반화로서의 계산과정(continuation)을 도입했고, 기술적 수준에서는 꼬리 호출(tail call)과 꼬리 재귀(tail recursion)를 위한 "극단적인" 최적화를 도입했다. 스킴은 학계가 요구하는 진(眞)과 미(美) - 즉 minimality와 orthogonality - 를 갖춘 아름다운 다이아몬드 같은 것이다. 그러나 그것은, 일상적인 프로그래밍에서 필요하지만 개념적인 아름다움을 해칠 수 있는 많은 실용적인 것들을 포함하지 않고 있다.


위에서 언급된 몇몇 용어에 대한 설명에 관심이 있으면 다음 링크를 참조할 것.


1970년대가 끝날 즈음, 여러 Lisp의 변종들이 사용되고 있었다. CL은 이러한 다양함에 대한 해결책으로 시작되었다 - 당시 존재하던 여러 Lisp 들의 장점들을 결합하고 단점들을 피하여 단일한 Lisp 버젼을 제공하겠다는. 또한 CL은 스킴에서 배운 교훈들을 포함하는 더 큰 한걸음이기도 했다. (렉시컬 스코핑(lexical scoping)은 CL에 채용되었다. 계산과정(continuation)은 실용적으로 사용되기에는 너무 복잡하다고 판명되어 포함되지 않았다. 꼬리 재귀에 대한 최적화는 구현기술로서 사용되는 것이 자연스러웠으므로, 표준화에는 포함되지 않았다.)

이를 참조하면 지금 Lisp을 사용하려고 할 때 무엇을 써야 할 지를 결정하기 위한 힌트를 얻을 수 있을 것이다. 만일 실용적인 "real-world" 문제에 적용하기 위해서라면, CL을 골라야 한다. 만일 계산과정(continuation)에 대한 실험을 한다던가 하는 학술적인 연구를 하기 위함이라면, 스킴을 고를 수 있다. 두 언어 모두 여전히 사용되고 있으며, 각각의 사용자 공동체로부터 충분한 지원을 받을 수 있다.

나는 몇가지 이유에서 CL을 사용하기로 결정했다. 그중 몇가지는 이 소개문서 중간에 드러날 것이다. 내가 스킴에서 좋아하지 않는 점은 그것이, 어떤 특정한 프로그램을 표현하는 하나의 옳은 방식이 존재한다, 라는 개념을 가지고 있는 언어라는 점이다. CL은 훨씬 더 유연해 보인다.

하지만, 스킴에 관한 많은 출판물이나 문서들이 CL에도 마찬가지로 적용되므로 - 예를 들어 렉시컬 클로저가 무엇인가에 대한 문서들 - 앞으로 스킴에 대한 몇몇 참고자료도 포함하기로 한다.

(본질적으로, 내 메시지는 이것이다: CL이나 스킴 중에 무엇을 고르는지는 중요하지 않다. 그건 당신의 특정한 필요에 달린 것이다. 그러므로, 맘에 드는 것을 골라라. 사실 두 언어 모두, 연구나 실용적인 일들을 하기에 충분한 유연성을 제공한다. 하지만 이 소개문서의 많은 부분은 CL을 다루고 있으므로, 만일 스킴을 골랐다면 다른 소개문서를 찾아보는 것이 좋을 것이다. 아래의 Link 섹션을 참조하라.)


이 문서를 보는 방법에 대하여: 나는 이 문서를, 순서대로 보는 것이 자연스럽게 만들기 위해 노력했다. 물론, 몇몇 섹션을 건너뛰거나, 특히 파트 I 과 파트 II 간에 왔다갔다 하면서 보는 것은, 당신의 자유이다. 하지만 뒤의 몇몇 섹션은, 당신이 Lisp 예제 코드에 대한 어느 정도의 경험이 있을 것을 요구한다. 이를 위한 충분한 포인터가 본문 중에 제시될 것이다.


3. CL의 실질적 요약

CL이 제공하는 것들에 대한 좋은 한페이지짜리 개요는 http://www.lisp.org/table/objects.htm에서 찾을 수 있다. 이는, CL의 일부인 CLOS (the Common Lisp Object System) 의 객체지향적 측면에 촛점을 맞추고 있으나, 그 외의 함수적(functional)이나 행동지침적(imperative) 측면에 대해서도 좋은 요약을 제공하고 있다.

Xanalys에서 제공하는 또 하나의 좋은 요약은 http://www.lispworks.com/products/lisp-overview.html에서 찾을 수 있다.

4. 최초의 장애물

Lisp의 역사는, 다른 프로그래밍 언어들 - 특히 Algol/C 패밀리의 언어들 - 과 다르다. 따라서 Lisp 공동체는 여러 레벨에서 다른 표현과 용어들을 개발해 왔다. 아래는 혼동을 피하기 위한 몇가지 해명이다.

5. Lisp의 역사

아래의 매우 잘 쓰여진 두개의 페이퍼에서, CL과 스킴을 포함하는 Lisp의 전체 역사에 대한 충분한 정보를 얻을 수 있다. 어떤 부분에서는 범죄 소설을 읽는 기분까지 느끼게 할 정도. - 강추!

후자는 Lisp에 대한 상당히 완전한 서지정보도 포함하고 있다.

(이들과, Herbert Stoyan이 작성한 Lisp의 역사에 대한 다른 페이퍼들을 혼동하지 말도록. 내가 보기에 그것은 읽기도 어렵고, 좀 이상한 결론에 도달하고 있는 것 같다.)

6. Lisp의 기술적 배경

전술한 대로, Lisp은 코드와 데이터를 동일한 방식으로 다룸으로써 계산에 대한 완전한 이론을 포함하는데, 이것이 Lisp을 그렇게 강력하게 만드는 주요한 원천이다. 아래의 두 글은 이것이 실제로 무엇을 의미하는지에 대한 좋은 설명을 해 주고 있으므로 추천할 만 하다. (그들은 "meta-circular interpreters"의 개념을 다루고 있다. 겁먹지 말길. 보기처럼 복잡한 것은 아니다.) Lisp의 힘을 알기 위해서는 적어도 처음 것은 꼭 읽어야 한다고 생각한다.

... 그리고 또한, 이 글은 Lisp의 기본적인 폼들에 대한 좋은 설명도 제공한다.

위의 "The Roots of Lisp"이란 글이 맘에 들었고, meta-curcular interpreters에 대해 더 알고 싶다면, 아래의 글에서 더 깊은 토의와 그걸 사용해서 할 수 있는 일들에 대한 비전을 얻을 수 있다. 그와 더불어, 렉시컬 클로저(lexical closure), 다이나믹 바인딩(dynamic biding) 등에 대한 유용한 사실들을 배울 수 있다.

(이 글은 속편이 있을 것처럼 말하고 있지만, 그런 것은 쓰여지거나 발표된 적이 없다. 그러므로 찾지 말 것: 아니면, 연습삼아 한번 완성시켜 보던가. ;)

7. 구할 수 있는 구현들

다음 링크에서 CL의 구현들에 대한 리스트를 찾을 수 있다: http://alu.cliki.net/Implementation. 나는 이 중 일부만을 좀 자세히 살펴봤을 뿐이다. 많은 Lisp 프로그래머들은 개발환경으로 emacs나 xemacs를 선호하지만, 나는 좀 더 현대적인 IDE를 선호하므로, 이 점이 내 선택 가능성을 많이 축소시켰다. (이 점에 대해서 논쟁하지 말 것. 이는 단지 개인의 취향의 문제이므로. 만일 emacs를 이용하여 IDE를 설정하는 방법을 알고 싶으면, http://cl-cookbook.sourceforge.net/windows.html이 가장 유용한 정보를 제공할 것이다.)

애플 매킨토시(Mac OS X)를 위한 추천: LispWorks for Macintosh는 뛰어난 IDE이고, 그 개인용 버젼은 무료로 다운로드 가능하다. Macintosh Common Lisp도 매우 좋은 IDE이지만, 이는 LispWorks에 비해 Mac OS X에 잘 통합되어 있지 못하다. Digitool에서는 MCL의 30일간 무료 시험 사용을 허용하고 있다. CLISP, ECL, OpenMCL, SBCL 등이 Mac OS X 용으로 존재하나, 그들은 IDE가 없다는 (내게는) 중요한 문제가 있다. Franz, Inc. 는 Mac OS X를 위한 Allegro Common Lisp의 IDE를 제공할 예정이지만, 확정된 계획은 없다. 따라서 너무 기대하지 말 것.

나는 LispWorks와 Macintosh Common Lisp을 둘 다 사용한다. 하지만 이것은 하나를 고르라는 추천이 아니다. 자신의 요구사항은 자신이 체크하도록!

파트 II: 독학을 위한 절충적 가이드

NOBODY expects the Spanish Inquisition! Our chief weapon is suprise...surprise and fear...fear and surprise.... Our two weapons are fear and surprise...and ruthless efficiency.... Our *three* weapons are fear, surprise, and ruthless efficiency...and an almost fanatical devotion to the Pope.... Our *four*...no... *Amongst* our weapons.... Amongst our weaponry...are such elements as fear, surprise.... I'll come in again....
- Monty Python

여기서는 CL의 여러 측면을 이해하는데 도움이 될 수 있는 힌트와 참고자료들을 주로 소개한다. (주로 표준 라이브러리에 대한 이야기다.)

8. 참고 자료

일상적인 프로그래밍 시에, 당신은 함수정의나 명확한 구문정의 등등을 찾아 볼 수 있는 참고자료들을 필요로 하게 된다. 어떤 사람들은 책 형태를, 어떤 사람들은 온라인 형태를 선호한다.

현재의 CL 표준은 1995년에 발표된 ANSI 표준에 정의되어 있고, 그것이 CL의 최종적인 정의이다. 그러나 그것은 스펙만을 다루고 있고, 예를 들어 그 배경의도 등이 전혀 설명되어 있지 않기 때문에 읽기 어렵다.

1990년대 초에, Guy L. Steele는, "Common Lisp the Language" 라는 책의 2판을 편집했는데, 그것은 그 시점에서의 CL 표준화에 대한 리포트였고, 최종 ANSI 표준과 아주 가까운 형태를 가진다. (이 판은 1980년대에 발표된 초판의 개정판이므로 일반적으로는 CLtL2 라고 불린다. 초판 - CLtL - 은 더 이상 사용되지 않는다.) 비록 CLtL2가 ANSI CL의 몇몇 특성을 다루지 못하고 있고, 또한 작은 차이점들도 있지만, 단순한 스펙 이상의 좋은 설명을 제공한다는 큰 장점이 있으므로, 일반적으로 개론서로서 추천할 만 하다. 이 장점은 스펙에 대한 이해를 아주 쉽게 한다. 그렇지만 여전히 ANSI 스펙을 꼭 가지고 있을 필요가 있는데, 이는 특정 정의의 정확한 세부사항들을 참조하기 위해서이다. 또한 ANSI 문서는 매우 유용한 용어집을 포함하고 있다.

다행히도 ANSI CL과 CLtL2 둘 다, HTML(과 PDF,PS) 문서의 형태로 온라인으로 구할 수 있다. HTML 버젼까지 다운로드하여 사용할 수도 있다. 다음이 그 링크들이다.

(이 "HyperSpec" 버젼의 편집자는, 이것이 확실한 스펙이 아니라, 단지 공식 ANSI 문서에서 추출된 것이라는 점을 강조한다. 하지만 이것은 단지 법적인 문제일 뿐, HyperSpec을 거의 확실하게 믿어도 별 문제는 없을 것으로 생각된다. 사실, 이것은 같은 TeX 소스 코드에서 생성되었다.)

(조심할 것: CLtL2는 소위 "Series" 매크로와 "Generators and Gatherers"라는 lazy iterators를 구현하는 부분에 대한 부록을 포함하고 있다. 이들은 ANSI CL에 포함되지 않았다. 이들이 왜 CLtL2에 포함되었다가 ANSI CL에서 다시 빠지게 되었는지는 알 수 없지만, 아마도 그것들은 너무 실험적이었던 것으로 생각된다. "Series" 매크로는 http://series.sourceforge.net에서 별도의 라이브러리로 구할 수 있다.)

만일 인쇄물 형태를 선호한다면, 구하기 위해서 좀 수고를 해야 한다. CLtL2는 절판인 듯 하지만 Ebay에서 중고를 구할 수 있을 것이다. Amazon과 같은 몇몇 (온라인) 서점에서는 아직 구할 수 있다. 또한 출판사의 웹사이트(http://www.bh.com/digitalpress/)에서 구입을 시도해 볼 수도 있을 것이다.

ANSI 문서는 http://global.ihs.com/에서 구할 수 있지만, 1000페이지가 넘기 때문에 특별히 편하거나 유용할 거라고는 생각되지 않는다. 더구나 거의 $400이나 하는 가격은 너무 비싸다.

Paul Graham의 "ANSI Common Lisp"은 좋은 책이지만, 참고 목적으로는 그렇게 유용하지는 못한 것 같다. 일반적으로 - 즉 자바 언어같은 경우 - 나는 인쇄된 스펙을 선호하지만, CL의 경우에는 전자문서 형태로 충분하고 생각한다.

9. 진짜 기초

Paul Graham은 "ANSI Common Lisp"이라는 ANSI Common Lisp에 대한 좋은 책을 썼다. 잘 읽히는 책이고, 또한 다행히도 저자는 첫 두 챕터를 그의 홈페이지에서 제공하고 있다. 두번째 챕터는 특히 권할 만한데, 이는 CL로의 프로그래밍이 어떠한지를 직접 경험할 수 있는 좋은 예제들을 제공한다.

그의 스타일이 맘에 든다면, 그 페이지의 링크를 통해 책을 구입할 수 있다.

이후로 당신이 찾고자 하는 대부분의 정보는 CLtL2, 그리고(또는) ANSI 스펙에서 쉽게 찾을 수 있을 것이다. 아래는, 내 생각에 조금 찾기 힘들지도 모를 몇몇 정보들에 대한 것이다.


파트 II의 나머지 부분들을 완전히 이해하기 위해서는, "The Roots of Lisp" (http://www.paulgraham.com/rootsoflisp.html) 이나, "ANSI Common Lisp Chapter 2" (http://www.paulgraham.com/lib/paulgraham/acl2.txt ) 를 읽었거나, 혹은 다른 방법으로 Lisp 예제 코드들을 접해 보았어야 한다.


10. 고급 기초

조만간에 다음과 같은 이슈들을 접하게 될 것이고, 이들은 다시 다른 작은 이슈들과 연관될 것이다.

11. 매크로

CL의 매크로 기능은 이 언어의 가장 흥미있는 점 중의 하나이다. 이는 당신 자신의 프로그래밍 언어 구문을 정의할 수 있는, 단순한 함수 이상의 매우 강력한 수단이다.

매크로는 그 강력함과 이해하기 힘들어 보인다는 점 때문에, 일반적으로 고급 주제로 인식된다. 하지만 나는 그것이 개념적으로 매우 단순하고 쓰기 쉽다는 점을 발견했다.

매크로에 대한 매우 뛰어난 설명과 사용법은 Paul Graham의 "On Lisp" 에서 찾을 수 있다. 이는 절판되었지만, 다음 URL에서 무료로 다운받을 수 있다.

아래는 내 생각에 주의가 필요하다고 생각되는 부분들이다.

12. 객체지향 기능 (CLOS)

Common Lisp Object System(CLOS)은 ANSI CL의 일부분이다. 하지만 표준에 늦게 더해졌기 때문에, 어떤 회사들은 구현에 시간이 걸렸다. 오늘날에는 거의 모든 구현들이 CLOS에 대한 지원을 제공한다. (어떤 회사들은 이를 자기네 CL 구현의 뛰어난 기능으로 광고하기도 하기에, 어떤 때는 이런 점이 좀 혼란스럽게 느껴진다. 정확하게 말하면 한 CL 시스템은, CLOS에 대한 완전한 구현을 포함하지 않는 한, ANSI 표준을 구현하고 있다고 주장할 수 없다.)

CLOS는 클래스, 서브클래싱(subclassing), 다중 상속, 다중 메소드, 전/후/주변 충고(before-, after- and around advices)들을 포함한다. 이것만으로도 다른 객체지향 언어들이 제공하는 기능들을 충분히 넘어선다.

이 외에도 소위 "Meta-Object Protocol"(MOP)라고 불리는 기능이 추가되었는데, 이는 런타임시에 클래스 계층구조와 메소드 정보 등을 살펴보고 조작할 수 있도록 하는 기능이다. MOP는 ANSI CL 표준의 일부분은 아니지만 사실상의(de-facto) 표준이 되었는데, 이는 거의 모든 CLOS/MOP 구현들이 같은 소스에서 나왔기 때문이다. (CLOS와 MOP는, 자바 언어와 그의 reflection API의 경우와 같이 서로 분리된 것이 아니고, MOP가 CLOS를 포함하는 집합이라고 생각할 수 있다.)

CLOS와 MOP에 대한 훌륭한 개요는 다음 논문을 참조하라.

CLOS의 설계 근거(design rationale)는 다음 논문에 나와 있다.

Jeff Dalton은 (MOP 부분 외의) CLOS에 대한 간략한 가이드를 http://www.aiai.ed.ac.uk/~jeff/clos-guide.html 에서 제공한다. MOP에 대한 참고자료는 ANSI HyperSpec과 유사한 스타일로 http://www.lisp.org/mop/에서 제공된다. (외부로의 링크는 대부분 깨져 있지만, 참고자료 자체는 볼 수 있다.)

Barry Margolin은 comp.lang.lisp에서 좋은 경험법칙을 제공했다:

MOP로 가능한 일에 대한 자세하고 인상적인 예제는 다음 논문에서 찾을 수 있다.

추가적 주의사항:

13. LOOP 기능

LOOP는 CL의 또 하나의 표준 기능으로서, Algol/Wirth 언어들과 유사한 스타일로 반복(iteration)을 표현할 수 있게 해 준다. 다음은 10개의 별을 찍는 loop의 예이다.

(loop for i from 1 to 10
      do (format t "*"))

여기서도 역시, CLtL2는 좋은 정보소스이다. 그러나 당신은 곧 loop를 사용하는데 있어서, 수많은 다른 스타일의 가능성과 결합들이 존재한다는 것을 알게 될 것이다. 내 생각엔, 모든 이들 세부사항을 배우는 것은 너무 많은 시간이 걸리고 별로 의미가 없다는 느낌이다. LOOP 기능의 목적은 분명히, 어떤 종류의 "자연스러운" 영어처럼 보이는 반복식들을 표현할 수 있게 하는 것이고, 이것이 소스코드의 이해를 쉽게 하는 경우들도 존재하는 것은 사실이다. (이는 또한, CL에 포함되어 있는 domain-specific 언어의 좋은 예이다 - 반복 이라는 도메인.)

다음은 더 재미있는 LOOP 기능의 사용예이다. (Matthew Danish 작.).

(defun fibonacci (n)
   (loop for a = 1 then (+ a b)
         and b = 0 then a ;  stepping in parallel
         repeat n
         collect b))

보는 바와 같이, LOOP를 사용하는 의도된 방법은, 단지 반복을 표현할 수 있는 방법을 한번 추측해 보고, 그것이 되는지를 보는 것이다. 만일 안된다면, CLtL2나 ANSI 스펙에서 세부사항을 찾아보거나, 좀더 Lisp 다운 방식으로 반복과 재귀호출을 표현하는 것이다. (do, dotimes, mapcar 등등을 사용해서.)

하지만, 이건 단지 내 추측일 뿐이고, LOOP 기능 설계자의 참의도는 알 수 없다. (몇몇 사람들은, 세부사항들을 아주 쉽게 배울 수 있다고 주장하지만, 그 부분은 확신할 수 없다.)

14. 컨디션(Conditions)

컨디션은 자바와 유사한 언어들에서의 익셉션(exceptions)과 거의 비슷하다. 하지만 컨디션이 더 강력한데, 이는 예를 들어, 다른 일은 하지 않고 컨디션이 일어났던 부분에서부터 수행을 재개하도록 컨디션 핸들러가 Lisp 런타임 시스템을 유도하는 것도 가능하기 때문이다. 익셉션 핸들러에 익숙해 있다면 이는 처음엔 이상하게 보일 수도 있다: 익셥션은 항상 거기에서 뭔가 문제가 발생했다는 의미가 아닌가? 음, CL에서는 문제가 없어도 컨디션이 발생될 수 있다. 예를 들어, 멀티 스레드 코드가 동기화 되어야 한다던가, 다른 코드들이 어떤 특정 이벤트의 발생을 보고받아야 한다던가, 혹은 당신이 유용할 것이라고 생각되는 다른 어떤 것이건 간에. 또한, 진짜 문제를 알리는 컨디션의 경우, 수행 중에 사용자에 의해서건 자동으로건 문제를 수정할 수도 있다.

즉, 대부분의 객체지향 언어의 모델들이 CLOS의 특별한 경우인 것과 똑같이, 자바의 익셉션 처리는 CL의 더 강력한 컨디션 시스템의 특별한 경우이다.

CL의 컨디션 처리에 대한 훌륭한 개요와, 몇가지 재미있는 역사적 사실들에 대한 정보는 다음 논문에서 찾을 수 있다.

몇가지 주의:

15. 고급 프로그래밍 기술

나는 이미 Paul Graham의 책 "On Lisp"을 매크로 프로그래밍과 관련해서 언급했다. 이 책은 또한 많은 다른 고급 프로그래밍 기술들도 설명하는데, 예를 들면 유틸리티 함수의 생성, 고수준 함수, 데이터베이스 접근, 스킴의 계산과정(continuations)을 흉내내기, 멀티 프로세스, 비결정성, 파싱, 로직 프로그래밍, 객체 지향 등등이다. (하지만, 책의 많은 부분은 매크로를 다루고 있다.)

편의를 위해 다시 링크해 둔다.

16. 패키지(Packages)

자바는 괜찮은 모듈 시스템을 가지고 있는데, 그것을 이용하여 클래스들을 한데 묶어 패키지로 만들 수 있고, 그것들은 서로간에 어느정도의 보호를 가능하게 한다. 또한, 패키지 구조는 대응되는 파일과 디렉토리 구조에 반영되고, 이는 zip이나 jar 파일 내에 숨겨지게 된다. 이는 단순하지만 세밀하게 클래스 경로를 다룰 수 있게 하는데, 클래스 경로는 필요에 따라 자바 런타임에 의해 로드될 수 있는 클래스들을 찾을 수 있는 곳을 정의한다.

CL 역시, 정의(definitions)들(물론 클래스의 정의도 포함하여)의 묶음을 다룰 수 있는 패키지 시스템을 제공한다. 그러나, 여기에는 파일과 디렉토리 구조와의 대응 같은 것은 없다. CL의 패키지 시스템은 단지, 정의들이 Lisp 환경 내에서 런타임시에 어떻게 관리(arranged)되는가를 다룬다.

사실, CL의 패키지 시스템은 그보다 더 강력한데, 이는 일반적으로 말해 패키지 시스템이 심볼(symbols)들을 패키지화 하도록 허용하기 때문이다. CL에서의 정의들은 항상 심볼들에 의해 접근되므로, 정의들을 묶을 수 있는 기능은, 단지 더 일반적인 패키지 개념의 특수한 예이다. 다음은 패키지로 달리 무엇을 할 수 있는지에 대한 좋은 예제로, Kent M. Pitman에 의해 comp.lang.lisp 에 포스팅 되었던 것이다. (아래 예를 포함하는 완전한 메시지를 보기 위해서는 http://makeashorterlink.com/?E3B823F91 를 참조하라.)

즉, CL의 패키지 시스템은 심볼들의 묶음을 다루고, 그 부수효과(side effect)로 정의들의 묶음도 허용하지만, 시스템의 부분들의 검색이나 로딩은 전혀 다루지 않는다. CL 용어로 말하면, 후자들은 "시스템 생성 (system contruction)" 이라는 업무로 불린다.

따라서 이런 측면에서 혼동하지 말기 바란다. 자바의 패키지와 CL의 패키지는 우연히 같은 이름을 가지지만, (약간의 겹침은 있으나) 다른 용도로 사용된다.

CL은 단지, 시스템 생성을 위한 기본적인 지원들만을 정의한다. ("load"나 "require" 등의 함수들이 그것이다. - CLtL2와 ANSI 스펙을 보라.) 이 이슈에 대한 추가적인 정보는 다음 섹션에서 다뤄질 것이다.

17. 무엇이 빠졌나?

ANSI CL 표준화는 1994년에 완료되어 1995년에 발표되었다. 그때는 자바가 거의 나오려는 참이었지만, 아직 공표되지는 않은 시점이었다. 그때는 또한 인터넷의 상업적 부상 이전이었다. 과거 7년 동안, 프로그래밍에 대한 지원은 명백히 여러 방향으로 진화해 왔다. 불행히도 그동안 CL의 "공식적인" 표준화는 계속되지 않았다. 많은 유행하는(fashionable) 프로그래밍 언어에서 요즘은 당연한 것으로 여겨지고 있는 여러가지 것들이, ANSI CL에는 포함되어 있지 않다. 모듈 기능("시스템 생성"), 유니코드 지원, 플랫폼 독립적인 GUI 라이브러리, 소켓과 TCP/IP, XML, 웹서비스 등등 - 당신이 좋아하는 것을 여기 추가해도 좋다 - 이 포함된다.

그러나 Lisp의 세계는 그동안 가만 있지는 않았다. ANSI CL 표준에 명세되어 있지 않다는 것이, 그것이 존재하지 않는다는 뜻은 아니다.

두가지 널리 쓰이는 시스템 생성 기능(facilities)은 ASDF (http://www.cliki.net/asdf)와 MK-DEFSYSTEM (http://www.cliki.net/mk-defsystem) 이다. 또한 몇몇 CL 구현들은 자신의 시스템 생성 지원 기능을 가지고 있따. Allegro Common Lisp, LispWorks, CLISP은 유니코드 지원을 제공한다. CLIM은 플랫폼 독립적인 GUI 라이브러리로 Franz, Xanalys, Digitool 등의 회사에서 지원된다. 대부분의 쓸만한 CL 구현들은 소켓과 더 진보된 네트웍 기능을 지원한다. CL-XML은 XML을 다룰 수 있는 라이브러리이다.

따라서 기본적으로, 만일 뭔가 라이브러리가 필요하다면 구글(Google)을 이용하여 쓸만한 라이브러리를 찾아낼 수 있을 것이다. 또한 아래의 링크들도 참고하라.

파트 III: 링크들

The television screen is the retina of the mind's eye.
Therefore, the television screen is part of the physical structure of the brain.
Therefore, whatever appears on the television screen emerges as raw experience for those who watch it.
Therefore, television is reality, and reality is less than television.
- Professor O'Blivion in Videodrome, by David Cronenberg

아래는 유용하고 재미있는 링크들이다. 전부는 아니지만 몇몇은 위의 텍스트에서 이미 언급되었다.

18. 개인적 웹사이트

19. CL 참고자료들

20. 배경 정보

21. 정보 모음, 링크 모음, 소프트웨어

22. 스킴 링크

23. 저작권 문제들

Acknowledgements

Many thanks (in alphabetical order) to Tom Arbuckle (http://www.cs.uni-bonn.de/~arbuckle/), Joe Bergin (http://csis.pace.edu/~bergin/) and Richard Gabriel (http://www.dreamsongs.com/) for providing lots of useful feedback on the draft version.

Further thanks for even more feedback go to Paolo Amoroso, Marco Antoniotti, Tim Bradshaw, Christopher Browne, Thomas F. Burdick, Wolfhard Buß, Bill Clementson, Matthew Danish, Biep Durieux, Knut Aril Erstad, Frode Vatvedt Fjeld, John Foderaro, Paul Foley, Erann Gatt, Martti Halminen, Bruce Hoult, Arthur Lemmens, Barry Margolin, Nicolas Neuss, Duane Rettig, Dorai Sitaram, Aleksandr Skobelev, Thomas Stegen, Gene Michael Stover, Raymond Toy, Sashank Varma and Espen Vestre. (Many of them are active participators in comp.lang.lisp.)

Valid HTML 4.0!