'Common Lisp'에 해당되는 글 2건
- 2010/03/20 새로운 웹 프로그래밍의 세계: Hunchentoot로 웹 사이트 제작하기 (11)
- 2010/01/08 ANSI Common Lisp 책을 읽고 있습니다. (5)
마지막으로 제가 웹 프로그래밍에 대한 내용을 발표하기로 하였습니다. ^^~
사실 이번에 웹 프로그래밍 발표를 위하여 여러가지 자료를 찾으면서 역시 Common Lisp은 긴 역사만큼 강력하다는 것을 느꼈습니다.
실제 활용을 하면서 Common Lisp을 만지다보니 그동안 잘 이해되지 않았던 부분도 자연스럽게 많이 이해되었습니다. ^^
Hunchentoot도 정말 쓸만하구나 하는 생각이 들었습니다.
참고로 http://www.adampetersen.se/articles/lispweb.htm 의 내용을 바탕으로 발표 자료를 준비하였습니다.
아울러 Ubuntu 9.10 + SBCL + Slime(2009-06-15) + Emace 22.2.1 환경 하에서 작성하였습니다.
사실 처음에 Windows 7 + Cygwin + SBCL + Slime으로 하다가 ASDF 관련한 GPG 에러가 있어서 Ubuntu로 갈아탔습니다. 이거 때문에 고생점 했었습니다.
1. Hunchentoot에 대하여
Hunchentoot는 Common Lisp으로 작성된 웹 서버입이며, 다이나믹한 웹사이트를 구성할 수 있도록 도와주는 툴킷입니다. 단독실행(Stand-alone)될 수 있으며, HTTP/1.1 스펙을 지원하고, DBMS와 연결 및 SSL 등을 지원합니다. 아울러 Hunchentoot는 Session을 처리할 수 있으며, Cookie 기반의 Session 처리와 Cookie를 사용하지 않는 Session 처리도 가능합니다. 또한 Logging을 하거나 사용자 정의 에러 처리를 할 수 있습니다.
1.1 Hunchentoot 설치
Hunchentoot는 당근 ASDF를 기반으로 쉽게 설치가 가능합니다. ASDF에 대한 자세한 사항은 나중에 한번 정리해서 올리겠습니다.
설치 절차는 다음과 같습니다.
CL-USER> (require 'asdf)
NIL
CL-USER> (require 'asdf-install)
("ASDF-INSTALL")
CL-USER> (asdf-install:install :hunchentoot)
Install where?
1) System-wide install:
System in /usr/lib/sbcl/site-systems/
Files in /usr/lib/sbcl/site/
2) Personal installation:
System in /root/.sbcl/systems/
Files in /root/.sbcl/site/
--> 1
Downloading 140293 bytes from http://weitz.de/files/hunchentoot.tar.gz ...
Installing /root/HUNCHENTOOT.asdf-install-tmp in /usr/lib/sbcl/site/,/usr/lib/sbcl/site-systems/
hunchentoot-1.1.0/
hunchentoot-1.1.0/acceptor.lisp
hunchentoot-1.1.0/CHANGELOG
hunchentoot-1.1.0/CHANGELOG_TBNL
hunchentoot-1.1.0/compat.lisp
hunchentoot-1.1.0/conditions.lisp
hunchentoot-1.1.0/cookie.lisp
.....
참고로 저의 경우 /usr/share/common-lisp/ 에 Common Lisp 관련된 자료를 몰아넣는 것을 좋아합니다. Slime도 여기에 설치했습니다. 아울러 ASDF-INSTALL 시 System-wide install을 하여 다른 계정으로도 쉽게 접근할 수 있도록 구성하는 것을 좋아합니다. Hunchentoot를 설치하다보면 계속 GPG 관련한 확인을 해주어야 합니다. 간단하게 ASDF-INSTALL 전에 다음과 같이 설정하시면 GPG 관련 항목을 더 이상 체크하지 않습니다.
CL-USER> (setq asdf-install::*verify-gpg-signatures* nil)
1.2 Hunchentoot 실행
ASDF를 이용하여 Hunchentoot가 정상적으로 설치했다면 다음과 같이 실행하면 됩니다. 8080포트를 사용합니다.
KLISPER> (hunchentoot:start (make-instance 'hunchentoot:acceptor :port 8080))간단하게 실행됩니다.
#<ACCEPTOR (host *, port 8080)>
1.3 Hunchentoot 종료
간단하게 종료됩니다. 사실 종료는 아직~ 해보지 않았습니다. :-)
KLISPER> (hunchentoot:stop *hunchentoot-server*)
2. CL-WHO에 대하여
사실 처음 CL-WHO를 들었을때 WHO(국제보건기구)에서 만들었나~ 하는 생각을 하였습니다. ㅎㅎㅎ CL은 당은 Common Lisp의 약자구요~ WHO는 With-Html-Output의 약자라는군요~ 참 했갈리게 하면서도 확실히 기억되는 이름입니다.
CL-WHO는 Lisp의 마크업 언어(Markup Language)입니다. Lisp의 특징인 S-expression을 기반으로 HTML, XHTML, XML 등의 마크업을 작성할 수 있도록 도와주는 넘입니다. 참고로 이와 비슷한 넘이 HTML-TEMPLATE란 넘이 있습니다.
아래의 Lisp 코드에서 (:XXX) 가 바로 CL-WHO 의 예 입니다.
KLISPER> (defmacro standard-page ((&key title) &body body)
`(with-html-output-to-string (*standard-output* nil :prologue t :indent t)
(:html :xmlns "http://www.w3.org/1999/xhtml" :xml\:lang "en" :lang "en"
(:head
(:meta :http-equiv "Content-Type" :content "text/html;charset=utf-8")
(:title ,title)
(:link :type "text/css" :rel "stylesheet" :href "/retro.css"))
(:body
(:div :id "header" ; Start all pages with our header.
(:img :src "/logo.jpg" :alt "Commodore 64" :class "logo")
(:span :class "strapline" "Vote on your favourite Retro Game"))
,@body))))
2.1 CL-WHO 설치
당근 ASDF 를 이용하여 다음과 같이 설치합니다.
CL-USER> (asdf-install:install :cl-who)
Install where?
1) System-wide install:
System in /usr/lib/sbcl/site-systems/
Files in /usr/lib/sbcl/site/
2) Personal installation:
System in /root/.sbcl/systems/
Files in /root/.sbcl/site/
--> 1
Downloading 19817 bytes from http://weitz.de/files/cl-who.tar.gz ...
Installing /root/CL-WHO.asdf-install-tmp in /usr/lib/sbcl/site/,/usr/lib/sbcl/site-systems/
cl-who-0.11.1/
cl-who-0.11.1/CHANGELOG
cl-who-0.11.1/cl-who.asd
.....
3. Parenscript 에 대하여
이름과 같이 Common Lisp 하에서 JavaScript를 CL-WHO와 같이 S-expression으로 표현할 수 있도록 도와주는 넘이 Parenscript 입니다. 이번 예제에서는 많이 쓰지 않았습니다. 하지만 재미 있는 기능이 많은 것 같습니다. :-)
이렇게 사용된다고 하네요~
(lambda (x)
(case x
(1 (loop repeat 3 do (alert "foo")))
(:bar (alert "bar"))
(otherwise 4)))
상기 Lisp 코드가 변환되면 이런 JavaScript 코드가 나온다고 합니다.
function (x) {
switch (x) {
case 1:
for (var _js1 = 0; _js1 < 3; _js1 += 1) {
alert('foo');
};
return null;
case 'bar':
return alert('bar');
default:
return 4;
};
};
4. K-Lisper 들을 위한 Lisp 책 투표 사이트 구축하기
자 이제 Common Lisp에서 웹 프로그래밍을 하기 위한 환경들을 살펴보았으니 본격적으로 웹 프로그래밍을 시작해보겠습니다.
예제로 만들어볼 웹 사이트를 간단하게 설명드리면, K-Lisper들이 자신이 선호하는 책에 투표를 하면 투표 결과가 바로 나오며, 만약 선호하는 책이 없으면 등록할 수 있는 웹 사이트입니다.
구조는 간단하지만, 간단한 투표 시스템을 만들려고 해도 사실 어려운 것이 사실입니다. 하지만 Common Lisp을 사용하였을 때 얼마나 효과적으로 웹 프로그래밍이 가능한지 한번 확인해보시기 바랍니다. :-)
4.1 패키지 설정
K-Lisper 책 투표 사이트를 위한 패키지를 새로 만듭니다.
CL-USER> (defpackage :klisper (:use :cl :cl-who :hunchentoot :parenscript))
#<PACKAGE "KLISPER">
자~ 만든 패키지로 이동합시다.
CL-USER> (in-package :klisper)
#<PACKAGE "KLISPER">
4.2 책(Book) 클래스 정의 및 로직 구성
Lisp에도 클래스가 있어라고 이야기하시는 분이 있다면, 김영태님이 발표하신 CLOS에 관한 내용을 확인해보시기 바랍니다. 제 블로그에 Lisp의 객체지향은 그 무엇보다 강력했다. 란 제목으로도 올려놨습니다.
우선 책 투표 사이트이므로 책(Book) 클래스를 만들겠습니다.
KLISPER> (defclass book()
((name :initarg :name)
(votes :initform 0)
)
)
#<STANDARD-CLASS BOOK>
상당히 간단한 책 클래스입니다. 필수적으로 입력받아야 하는 책 명(name)과 얼마나 투표했는지 나타내는 votes가 존재합니다.
그럼 새로운 책을 하나 만들어 볼까요~ :-)
예제 삼아 Lisp을 좋아하는 사람들의 그룹(http://groups.google.com/group/lisp-korea)에서 처음 공부하였던 책 제목을 넣어 봤습니다.
KLISPER> (setf klispers-books (make-instance 'book :name "Common Lisp: A Gentle Introduction to Symbolic Computation"))
; in: LAMBDA NIL
; (SETF KLISPER::KLISPERS-BOOKS
; (MAKE-INSTANCE 'KLISPER::BOOK :NAME
; "Common Lisp: A Gentle Introduction to Symbolic Computation"))
; ==>
; (SETQ KLISPER::KLISPERS-BOOKS
; (MAKE-INSTANCE 'KLISPER::BOOK :NAME
; "Common Lisp: A Gentle Introduction to Symbolic Computation"))
;
; caught WARNING:
; undefined variable: KLISPERS-BOOKS
;
; compilation unit finished
; Undefined variable:
; KLISPERS-BOOKS
; caught 1 WARNING condition
#<BOOK {D321AE9}>
생성된 Common Lisp 책 객체가 정상적으로 동작하는지 확인하기 위하여 책 명을 확인해보겠습니다.
KLISPER> (name klispers-books)
"Common Lisp: A Gentle Introduction to Symbolic Computation"
잘 들어가 있군요~ :-) 투표 건수도 확인해보겠습니다.
KLISPER> (votes klispers-books)
0
네~ 아직 투표는 하지 않았으니 0건이 맞습니다. 한번 투표해보겠습니다.
KLISPER> (incf (votes klispers-books))
; (LET* ((#:TMP1390 KLISPER::KLISPERS-BOOKS)
; (#:G1391 1)
; (#:NEW1389 (+ (KLISPER::VOTES #:TMP1390) #:G1391)))
; (FUNCALL #'(SETF KLISPER::VOTES) #:NEW1389 #:TMP1390))
;
; caught WARNING:
; undefined variable: KLISPERS-BOOKS
;
; compilation unit finished
; Undefined variable:
; KLISPERS-BOOKS
; caught 1 WARNING condition
1
KLISPER> (votes klispers-books)
1
incf 는 1씩 증가시켜주는 function 입니다. 제 Emacs는 WARNING되는 내용을 확인할 수 있도록 설정되어 있어 약간씩 내용이 틀릴 수 있습니다. 참고하세요~
책(Book) 클래스를 더 확장하겠습니다.
KLISPER> (defclass book()
((name :reader name
:initarg :name)
(votes :accessor votes
:initform 0)
)
)
#<STANDARD-CLASS BOOK>
사용자가 선택한 책을 찾아서 투표해주는 메소드를 만들겠습니다.
KLISPER> (defmethod vote-for (user-selected-book)
(incf (votes user-selected-book))
)
STYLE-WARNING: Implicitly creating new generic function VOTE-FOR.
#<STANDARD-METHOD VOTE-FOR (T) {C847BF1}>
자~ 새로운 메소드를 통하여 한번 투표를 해보겠습니다.
KLISPER> (votes klispers-books) ; 현재 1건 투표됨
1
KLISPER> (vote-for klispers-books) ; 투표함
2
KLISPER> (votes klispers-books) ; 2건 투표됨.
2
책들을 담을 전역 변수를 만들겠습니다. 앞으로 이곳에 책들이 저장될 것입니다.
KLISPER> (defvar *books* '())
*BOOKS*
자~ 전역 변수를 기준으로 책 명으로 책을 찾아주는 메소드를 만들어 보겠습니다.
KLISPER> (defun book-from-name(name)
(find name *books* :test #'string-equal :key #'name))
STYLE-WARNING: redefining BOOK-FROM-NAME in DEFUN
BOOK-FROM-NAME
그리고 책이 존재하는지 여부를 확인하는 function을 만들어 보겠습니다.
KLISPER> (defun book-stored? (book-name)
(book-from-name book-name)
)
BOOK-STORED?
아울러 책을 투표된 건수를 바탕으로 정렬해서 출력하는 function도 만들겠습니다. 나중에 화면에 출력할때 투표건에 따라 정렬할 때 사용할 예정입니다.
KLISPER> (defun books()
(sort (copy-list *books*) #'> :key #'votes)
)
BOOKS
마지막으로 책을 추가하는 function을 만들어 보겠습니다.
KLISPER> (defun add-book(name)
(unless (book-stored? name)
(push (make-instance 'book :name name)
*books*)
)
)
ADD-BOOK
자~ 새로 만든 function들이 정상적으로 동작하는지 확인해보겠습니다.
KLISPER> (books) ; 현재 한권의 책도 없음.
NIL
KLISPER> (add-book "Common Lisp") ; 새로운 책 추가함.
(#<BOOK {C656311}>)
KLISPER> (book-from-name "Common Lisp") ; 책명으로 책을 찾음
#<BOOK {C656311}>
KLISPER> (add-book "Common Lisp") ; 같은 명칭의 책을 추가하였지만, 추가되지 않음. 즉 기능이 정상임.
NIL
KLISPER> (mapcar #'name (books)) ; 책 목록을 출력함.
("Common Lisp")
이로서 책 투표 사이트 구축을 위한 핵심 로직 구성이 끝났습니다. 이제 본격적으로 웹 페이지를 구성해 봅시다~
4.3 웹 사이트 구성
CL-WHO를 본격적으로 이용해볼 시간이 왔습니다. 간단하게 한번 CL-WHO를 테스트 해봅시다.
KLISPER> (with-html-output (*standard-output* nil :indent t)
(:html
(:head
(:title "K-Lisper's Books")
)
(:body
(:p "K-Lisper's is best!")
)
)
)
<html>
<head>
<title>
K-Lisper's Books
</title>
</head>
<body>
<p>
K-Lisper's is best!
</p>
</body>
</html>
"
<html>
<head>
<title>
K-Lisper's Books
</title>
</head>
<body>
<p>
K-Lisper's is best!
</p>
</body>
</html>"
표준적으로 사용할 HTML 페이지의 구조를 잡는 Macro를 작성하려고 합니다. 즉, XHTML의 공통적인 요소를 담고 있는 Macro 입니다. 이 Macro를 통하여 불필요한 요소를 없애고 변화되는 내용만 반영하게 만들것입니다.
KLISPER> (defmacro standard-page ((&key title) &body body)
`(with-html-output-to-string (*standard-output* nil :prologue t :indent t)
(:html :xmlns "http://www.w3.org/1999/xhtml" :xml\:lang "en" :lang "en"
(:head
(:meta :http-equiv "Content-Type" :content "text/html;charset=utf-8")
(:title ,title)
(:link :type "text/css" :rel "stylesheet" :href "/retro.css"))
(:body
(:div :id "header" ; K-Lisper's Books Header
(:img :src "/logo.jpg" :alt "K-Lisper" :class "logo")
(:span :class "strapline" "Vote on your favorite Lisp Book"))
,@body))))
STANDARD-PAGE
주의하셔야 할 점은 ,title 와 ,@body 의 , 는 마침표(.)가 아니라 쉼표(,)라는 것입니다.
자~ 첫 페이지인 index.htm을 한번 만들어 봅시다. Macro로 이미 정의한 standard-page의 위력이 발휘되는 순간입니다.
KLISPER> (defun index-page()
(standard-page
(:title "Klisper's Books")
(:h1 "Top KLisper's Books")
(:p "We'll wirite the code later..."
)
)
)
INDEX-PAGE
이제 만든 페이지를 index.htm으로 걸어 봅시다.
KLISPER> (push (create-prefix-dispatcher "/index.htm" 'index-page) *dispatch-table*)
(#<CLOSURE (LAMBDA #) {C70DCED}> DISPATCH-EASY-HANDLERS DEFAULT-DISPATCHER)
웹 브라우져에서 http://localhost:8080/index.htm 이 정상적으로 출력되는지 한번 확인해보세요~
이렇게 등록하는 절차를 더욱 쉽게 하도록 Macro를 사용하겠습니다.
KLISPER> (defmacro define-url-fn ((name) &body body)
`(progn
(defun ,name()
,@body)
(push (create-prefix-dispatcher ,(format nil "/~(~a~).htm" name) ',name)
*dispatch-table*)
)
)
DEFINE-URL-FN
그리고 다시 index 페이지를 작성해보겠습니다.
KLISPER> (define-url-fn (index)
(standard-page (:title "K-Lisper's Book Site")
(:h1 "Top Books!")
(:p "How about it?")
)
)
(#<CLOSURE (LAMBDA #) {BEE6D7D}> #<CLOSURE (LAMBDA #) {BB85A8D}>
DISPATCH-EASY-HANDLERS DEFAULT-DISPATCHER)
웹 브라우져에서 다시 http://localhost:8080/index.htm 을 입력하고 정상적으로 변경되었는지 확인해보세요~ 두번에 해야할 절차를 한번에 간단하게 끝냈습니다. 와우~ 매크로여~ :-)
본격적으로 index.htm 페이지에 투표를 할 수 있는 기능을 추가해보겠습니다.
KLISPER> (define-url-fn (index)
(standard-page (:title "K-Lisper's Top Books")
(:h1 "Vote on your all time favorite Lisp Books!")
(:p "Missing a book? Make it available for votes " (:a :href "new-book.htm" "here"))
(:h2 "Current stand")
(:div :id "chart" ; For CSS Style of Links
(:ol
(dolist (book (books))
(htm
(:li
(:a :href (format nil "vote.html?name=~a" (name book)) "Vote!")
(fmt "~A with ~d votes" (name book) (votes book))
)
)
)
)
)
)
)
STYLE-WARNING: redefining INDEX in DEFUN
(#<CLOSURE (LAMBDA #) {C9B40F5}> #<CLOSURE (LAMBDA #) {D94667D}>
#<CLOSURE (LAMBDA #) {AAB237D}> #<CLOSURE (LAMBDA #) {BB85A8D}>
DISPATCH-EASY-HANDLERS DEFAULT-DISPATCHER)
길어 보이긴 합니다만, 기종의 HTML 작업의 경우 JSP나 PHP 또는 ASP 파일을 각각 만들고 각각 서버에 올려서 다시 컴파일 되는 과정이나 인터프리팅 되는 과정을 거쳐서 결과가 나오지만, Common Lisp의 웹 프로그래밍은 전혀 파일이 필요없습니다.
따라서 언제라도 index.htm 을 바로 변경할 수 있으며 만약 미리 만든 lisp 파일을 load한다고 하여도 파일속의 내용이 현저하게 적습니다. 웹 브라우져로 HTML 소스를 확인해보신다면 아마 팍팍 느끼실 것입니다.
이제 투표 결과를 받는 페이지입니다.
KLISPER> (define-url-fn (vote)
(let ((book (book-from-name (parameter "name"))))
(if book
(vote-for book))
(redirect "/index.htm")
)
)
(#<CLOSURE (LAMBDA #) {D21BE9D}> #<CLOSURE (LAMBDA #) {D9A7965}>
#<CLOSURE (LAMBDA #) {D9B3E6D}> #<CLOSURE (LAMBDA #) {AAB237D}>
#<CLOSURE (LAMBDA #) {BB85A8D}> DISPATCH-EASY-HANDLERS DEFAULT-DISPATCHER)
index.htm에서 Vote! 를 클릭하면 vote.htm으로 왔다가 바로 redirect되어 /index.htm으로 돌아가게 되어있습니다. 여기서 주목할 점은 이전에 만들었던 function인 vote-for를 로직으로 바로 활용했다는 점입니다. 그리고 "name" parameter 역시 간단하게 바로 받아서 처리합니다.
얼마나 멋집니까~ 하하하~ ;-)
이제~ 새로운 책을 추가하는 페이지를 만들겠습니다. 투표할 목록에 원하는 책이 없는 경우 간단하게 책 명을 입력하는 페이지입니다.
KLISPER> (define-url-fn (new-book)
(standard-page (:title "Add a new book!")
(:h1 "Add a new book to the chart")
(:form :action "/book-add.htm" :method "post"
:onsubmit (ps-inline ; Client-side validation.
(when (= name.value "")
(alert "Please enter a name.")
(return false)))
(:p "What is the name of the book?" (:br)
(:input :type "text" :name "name" :class "txt"))
(:p (:input :type "submit" :value "Add" :class "btn"))
)
))
(#<CLOSURE (LAMBDA #) {BC8CD65}> #<CLOSURE (LAMBDA #) {DA52B0D}>
#<CLOSURE (LAMBDA #) {D9A7965}> #<CLOSURE (LAMBDA #) {D9B3E6D}>
#<CLOSURE (LAMBDA #) {AAB237D}> #<CLOSURE (LAMBDA #) {BB85A8D}>
DISPATCH-EASY-HANDLERS DEFAULT-DISPATCHER)
이 페이지에서 드디어 Parenscript 를 사용합니다. 중간에 ps-inline 부터 사용하며, 만약 내용이 없는 경우 다시 입력을 받을 수 있도록 JavaScript로 입력값 검증을 처리하는 부분입니다.
자 새로운 책명을 입력받았다면, 책을 추가하는 페이지입니다. JavaScript에서 이미 걸렸겠지만, 다시 한번 빈 내용이 들어오는지 확인합니다. 이런 처리까지 해주어야 정말 좋은 웹 프로그래밍이라고 생각합니다. 참고로 로직 상으로도 이미 book-stored? function을 통하여 중복 방지 처리가 되어있습니다.
KLISPER> (define-url-fn (book-add)
(let ((name (parameter "name")))
(unless (or (null name)(zerop (length name)))
(add-book name))
(redirect "/index.htm"))
)
(#<CLOSURE (LAMBDA #) {D274E35}> #<CLOSURE (LAMBDA #) {D9999F5}>
#<CLOSURE (LAMBDA #) {DA52B0D}> #<CLOSURE (LAMBDA #) {D9A7965}>
#<CLOSURE (LAMBDA #) {D9B3E6D}> #<CLOSURE (LAMBDA #) {AAB237D}>
#<CLOSURE (LAMBDA #) {BB85A8D}> DISPATCH-EASY-HANDLERS DEFAULT-DISPATCHER)
자~ 이제 index.htm에 있는 here 를 눌러서 새로운 책을 한번 추가해보세요~ :-)
여기까지가 Common Lisp의 새로운 웹 프로그래밍의 세계입니다. 다른 언어도 많은 장점을 제공하지만, Common Lisp이 당근 훌륭한 기능을 제공한다고 생각되네요~
아마 웹 브라우져의 내용이 궁금하신 분들이 많으시리라 생각됩니다. 한번씩 해보세요~ 따라하시기 편하도록 구성하였습니다. ;-)
'Architecture for Software > Lisp' 카테고리의 다른 글
| 제 1 회 Korea Lisp 세미나 후기 :-) (22) | 2010/05/03 |
|---|---|
| 드디어 우리나라 첫(?) Lisp 세미나가 열립니다! (10) | 2010/04/25 |
| 새로운 웹 프로그래밍의 세계: Hunchentoot로 웹 사이트 제작하기 (11) | 2010/03/20 |
| Clojure 개발 환경 구축하기 (8) | 2010/02/17 |
| Lisp의 객체지향은 그 무엇보다 강력했다. (0) | 2010/01/12 |
| ANSI Common Lisp 책을 읽고 있습니다. (5) | 2010/01/08 |
-
Subject 새로운것을 배우는것을 무서워하지 말자
2010/10/19 04:20
오래전부터 프로그래밍을 하면서 느낀것이 있다. 이 세상에 프로그래밍언어는 많고 내시간은 제한적이다. 프로그래밍언어는 매번 새롭게 개발되기도 하지만, 나의 시간은 늘어나지 않는다. 더군다...
-
Hybrid 2010/03/27 15:28
좋은글 잘 보고 갑니다~
그야 말로 피가 되고 살이 되는 내용이네요 ㅜㅜ
(하지만, 윈도우 환경이라 아직 실습 해볼 수 없다는 현실에 좌절만....~!)-
장선진 jangsunjin 2010/03/29 10:49
아네~ ^^ Cygwin + ASDF 가 성공했었는데.. 지금은 잘 안되네요~
다음에 Windows 환경에서 Cygwin + ASDF 를 설정하는 방법에 대하여 한번 정리해서 올리겠습니다~ ^^
-
-
레몬에이드 2010/03/30 09:20
와... 역시 선진님 답게 깔끔하고 멋진 정리입니다
다만 Lisp 코드를 전혀 읽지 못하는 안타까움이 ㅇㅅㅇ;;
요즘에 호기심에 이것저것 찔러보고 있는데
멘토가 깊이를 우선 시 하라고 해서 마음을 다시 잡고 있습니다.
그래서 선진님 공간에 살짝 발도장 찍고 갑니다 ㅎㅎ-
jangsunjin 2010/04/02 11:12
아네~ 오랜만입니다~ 지환님~
잘 지내고 계시지요~ 저희가 세미나를 준비중에 있습니다~
Lisp 세미나 열리면 꼭 참석해주세용~ :-)
-
-
전창민 2010/04/03 23:40
처음 뵙겠습니다.
코드 따라가다가 막히는 부분이 있는데요 ^^;
votes 와 name method 는 undefined function 이라고 나오는데 따로 정의하신부분이신가요 ?ㅎ-
전창민 2010/04/03 23:45
원문에 들어가서 찾아보니 결국 자문자답이 되었네요 -_-
루비와 비슷하게 자동으로 생성되는 슬롯을 정의해줘야 하더군요.
(defclass game ()
((name :reader name
:initarg :name)
(votes :accessor votes
:initform 0))) -
전창민 2010/04/03 23:53
밑으로 좀 더 진행하니 클래스 확장부분이 있었네요.
그럼 순서 조정이 필요할꺼 같네요 ^^;
KLISPER> (defclass book()
((name :reader name
:initarg :name)
(votes :accessor votes
:initform 0)
)
)
#<STANDARD-CLASS BOOK> -
전창민 2010/04/04 00:38
한시간 정도 걸려서 따라 해봤는데 정말 직관적인거 같군요.
폴그레이엄이 왜 lisp 로 viaweb 을 만들었는지 조금이나마 이해가 되네요. 정말 잘 정리해주셨네요 ^^ -
장선진 jangsunjin 2010/04/04 08:57
안녕하세요~ 전창민님 :-)
도움이 되셨다니~ 다행입니다.
예제 자체가 처음에 book~ 이란 클래스가 만든 후 확장하게 되어 있습니다.
저도 Lisp의 매크로가 이렇게 강력한지 이번에 알았습니다~ 후후후~
저희 Lisp을 좋아하는 사람들의 그룹에서 Lisp 전문 세미나를 준비중입니다. 아마 5월 1일경에 세미나를 주최하게 될 것같습니다. 오셔서 Lisp의 다른 세계도 알아보세요~ ;-)
-
-
-
장선진 jangsunjin 2010/04/04 19:53
네~ 감사합니다~ :-)
일정 진행 상황은 http://groups.google.com/group/lisp-korea 에서 확인하실 수 있습니당~ 추후에 제 블로그에도 공지하겠습니당~ ;-)
-
Common Lisp은 Lisp을 처음 접하시는 분들에게 상당히 훌륭한 책이라고 생각합니다. 저 역시 이 책을 Lisp을 좋아하는 사람들의 그룹에서 진행한 오프라인 스터디를 통하여 공부하였는데, 많은 도움이 되었습니다.
혹시 Common Lisp 책을 공부하시는 분들 중에 참고자료를 찾으시는 분들이라면 저희 그룹에서 진행한 오프라인 스터디 동영상을 한번 참고하시기 바랍니다. 저희 위키 사이트인 http://lisp-korea.wikispaces.com/Common+Lisp 에 동영상 강의를 잘 모아서 올려 놨습니다.
현재 Lisp을 좋아하는 사람들의 그룹 에서는 Practical Common Lisp 책을 바탕으로 함께 오프라인 스터디를 진행하고 있습니다.
음.. Practical Common Lisp 책에 대한 개인적인 의견은 책의 명성만큼 잘 정리된 책은 아닌듯합니다.
사실 그렇게 느끼는 이유중에는 제가 아직 Lisp의 많은 부분을 모르기 때문이기도 합니다.
해서 최근 Paul Graham 아저씨가 쓰신 ANSI Common Lisp을 읽고 있습니다. 저희 김영태님께서 소개해주셨는데, 정말 궨찮은 책인것 같습니다.
제 부족한 Lisp 실력에 따악 맞는 책인것 같습니다. :-)
국내에서는 해커와 화가로 유명하신 Paul 아저씨의 글을 읽으면서 따악 Lispy한 느낌을 받습니다.
뭔가 간결하면서도 따악 할말만 하시는 Paul 아저씨~ Lisp을 공부하시는 분이라면 한번 참고하시면 좋겠습니다. :-)
'Architecture for Software > Lisp' 카테고리의 다른 글
| Clojure 개발 환경 구축하기 (8) | 2010/02/17 |
|---|---|
| Lisp의 객체지향은 그 무엇보다 강력했다. (0) | 2010/01/12 |
| ANSI Common Lisp 책을 읽고 있습니다. (5) | 2010/01/08 |
| 첫 오프라인 Lisp 스터디 모임을 시작하였습니다. :-) (0) | 2009/09/23 |
| Lisp 오프라인 스터디를 본격적으로 시작하겠습니다. :-) (0) | 2009/09/14 |
| Lisp 오프라인 스터디를 시작하려고 합니다. (0) | 2009/09/08 |
-
-
장선진 jangsunjin 2010/01/09 19:25
^^ 그러시군요~
Lispy 한게 느낌이 좋지 않나요~ ㅎㅎㅎ
들어보니~ 뒤로갈수록 어렵다고 하더라구요~ 한번 같이 도전해 보아요~ ;-)
-
-
lisper 2010/01/30 19:51
참, HyperSpec을 꼭 설치해서 프로그래밍 도중에 참고하실 것을 권합니다. (그리고 위의 책 목록은 제 생각으로는 가장 짧고 지금까지 존재하는 경우의 방법중 가장 완벽하게 CL을 마스터하는 방법이라고 말씀드리고 싶네요)
-
장선진 jangsunjin 2010/01/30 21:36
아 좋은 책 추천해 주셔서 감사합니다.
특히 On Lisp 꼭 한번 읽고 싶습니다.
ANSI Common LIsp 책 완독한 후에 꼭 읽어보겠습니다.
특히 HyperSpec 말씀은 정말 맞습니다. 이맥스에서 잘 연결해서 사용하고 있습니다. :-)
-


