common-lispcommon-lisp 시작하기

비고

이것은 Common Lisp에서 간단한 hello world 함수입니다. Hello, World! 라는 텍스트가 인쇄됩니다 Hello, World! (따옴표는 없으며 개행 문자가 뒤따라야 함)를 표준 출력으로 보냅니다.

Common Lisp는 REPL로 알려진 인터페이스를 사용하여 대화식으로 주로 사용되는 프로그래밍 언어입니다. REPL (Read Eval Print Loop)을 사용하면 코드를 입력하고 평가 (실행)하고 결과를 즉시 볼 수 있습니다. REPL에 대한 프롬프트 (실행 코드를 입력하는 지점)는 CL-USER> 표시됩니다. CL-USER 이외의 다른 것들이 > 앞에 나타나기도하지만 이것은 여전히 ​​REPL입니다.

프롬프트 뒤에는 보통 하나의 단어 (즉, 변수 이름) 또는 양식 ( () 사이에 포함 된 단어 / 양식 목록) (즉, 함수 호출 또는 선언 등)이 제공됩니다. 다음 줄에는 프로그램이 출력하는 모든 출력 (또는 프로그램에서 아무 것도 인쇄하지 않으면 아무 것도 출력되지 않습니다.)과 표현식을 평가하여 반환되는 값이 표시됩니다. 일반적으로 표현식은 하나의 값을 반환하지만 여러 값을 반환하면 행당 한 번 나타납니다.

버전

번역 출시일
Common Lisp 1984-01-01
ANSI Common Lisp 1994-01-01

안녕하세요 세계

다음은 Common Lisp을 사용하는 REPL 세션에서 발췌 한 "Hello, World!" 함수가 정의되고 실행됩니다. REPL에 대한 자세한 설명은이 페이지 하단의 설명을 참조하십시오.

CL-USER> (defun hello ()
           (format t "Hello, World!~%"))
HELLO
CL-USER> (hello)
Hello, World!
NIL
CL-USER> 

이것은 " hello "Hello, World!" 문자열을 쓸 hello 라는 인자가없는 "함수"를 정의합니다 "Hello, World!" 그 다음에 표준 출력에 개행 문자가오고 NIL 반환합니다.

우리가 작성하는 함수를 정의하려면

(defun name (parameters...)
  code...)

이 경우 함수는 hello 라고하며 매개 변수를 사용하지 않고 실행되는 코드는 하나의 함수 호출을 수행하는 것입니다. lisp 함수에서 반환 된 값은 실행할 함수의 마지막 코드 비트이므로 hello(format t "Hello, World!~%") 반환 값을 반환합니다.

하나의 함수를 호출하는 lisp에서 write (function-name arguments...) 여기서 function-namefunction-name 이고 arguments... 는 호출에 대한 인수의 공백으로 구분 된 목록입니다. 함수 호출처럼 보이지만 예를 들어 위의 코드에서는 호출되는 defun 함수가 없으며 특수하게 처리되고 대신 함수를 정의하는 특별한 경우가 있습니다.

REPL의 두 번째 프롬프트에서 hello 함수를 정의한 후에는 (hello) 를 작성하여 매개 변수없이 호출합니다. 이것은 매개 변수 t"Hello, World!~%" 하여 format 함수를 호출합니다. format 함수는 주어진 인수에 따라 형식화 된 출력을 생성합니다 (C에서 printf 의 고급 버전과 비슷합니다). 첫 번째 인수는 출력 할 곳을 알려주고 t 는 표준 출력을 의미합니다. 두 번째 인수는 무엇을 인쇄 할 것인지 (그리고 추가 매개 변수를 해석하는 방법)를 알려줍니다. 지시문 (두 번째 인수의 특수 코드) ~% 는 형식에 줄 바꿈을 인쇄하도록 지시합니다 (예 : UNIX에서는 \n , Windows에서는 \r\n \n 쓸 수 있습니다). 형식은 일반적으로 NIL 반환합니다 (다른 언어에서는 NULL 과 비슷 NULL ).

두 번째 프롬프트 후에 Hello, World 가 인쇄되었고 다음 줄에는 반환 값이 NIL 됩니다.

안녕하세요, 이름

이것은 좀 더 고급 예제로서 일반적인 lisp의 몇 가지 기능을 보여줍니다. 우리는 간단한 Hello, World! 시작합니다 Hello, World! 기능을 설명하고 REPL에서 대화 형 개발을 시연합니다. 세미콜론의 모든 텍스트는 ; , 줄의 나머지 부분은 주석입니다.

CL-USER> (defun hello ()
       (format t "Hello, World!~%")) ;We start as before
HELLO
CL-USER> (hello)
Hello, World!
NIL
CL-USER> (defun hello-name (name) ;A function to say hello to anyone
       (format t "Hello, ~a~%" name)) ;~a prints the next argument to format
HELLO-NAME
CL-USER> (hello-name "Jack")
Hello, Jack
NIL
CL-USER> (hello-name "jack") ;doesn't capitalise names
Hello, jack
NIL
CL-USER> (defun hello-name (name) ;format has a feature to convert to title case
       (format t "Hello, ~:(~a~)~%" name)) ;anything between ~:( and ~) gets it
WARNING: redefining COMMON-LISP-USER::HELLO-NAME in DEFUN
HELLO-NAME
CL-USER> (hello-name "jack")
Hello, Jack
NIL
CL-USER> (defun hello-name (name)
       (format t "Hello, ~:(~a~)!~%" name))
WARNING: redefining COMMON-LISP-USER::HELLO-NAME in DEFUN
HELLO-NAME
CL-USER> (hello-name "jack") ;now this works
Hello, Jack!
NIL
CL-USER> (defun hello (&optional (name "world")) ;we can take an optional argument
       (hello-name name)) ;name defaults to "world"
WARNING: redefining COMMON-LISP-USER::HELLO in DEFUN
HELLO
CL-USER> (hello)
Hello, World!
NIL
CL-USER> (hello "jack")
Hello, Jack!
NIL
CL-USER> (hello "john doe") ;note that this capitalises both names
Hello, John Doe!
NIL
CL-USER> (defun hello-person (name &key (number))
       (format t "Hello, ~a ~r" name number)) ;~r prints a number in English
HELLO-PERSON
CL-USER> (hello-person "Louis" :number 16) ;this doesn't quite work
Hello, Louis sixteen
NIL
CL-USER> (defun hello-person (name &key (number))
       (format t "Hello, ~:(~a ~:r~)!" name number)) ;~:r prints an ordinal
WARNING: redefining COMMON-LISP-USER::HELLO-PERSON in DEFUN
HELLO-PERSON
CL-USER> (hello-person "Louis" :number 16)
Hello, Louis Sixteenth!
NIL
CL-USER> (defun hello-person (name &key (number))
       (format t "Hello, ~:(~a ~@r~)!" name number)) ;~@r prints Roman numerals
WARNING: redefining COMMON-LISP-USER::HELLO-PERSON in DEFUN
HELLO-PERSON
CL-USER> (hello-person "Louis" :number 16)
Hello, Louis Xvi!
NIL
CL-USER> (defun hello-person (name &key (number)) ;capitalisation was wrong
       (format t "Hello, ~:(~a~) ~:@r!" name number))
WARNING: redefining COMMON-LISP-USER::HELLO-PERSON in DEFUN
HELLO-PERSON
CL-USER> (hello-person "Louis" :number 16) ;thats better
Hello, Louis XVI!
NIL
CL-USER> (hello-person "Louis") ;we get an error because NIL is not a number
Hello, Louis ; Evaluation aborted on #<SB-FORMAT:FORMAT-ERROR {1006641AB3}>.
CL-USER> (defun say-person (name &key (number 1 number-p)
                                      (title nil) (roman-number t))
       (let ((number (if number-p
                 (typecase number
                   (integer
                (format nil (if roman-number " ~:@r" " ~:(~:r~)") number))
                   (otherwise
                (format nil " ~:(~a~)" number)))
                 "")) ; here we define a variable called number
         (title (if title 
                (format nil "~:(~a~) " title)
                ""))) ; and here one called title
         (format nil "~a~:(~a~)~a" title name number))) ;we use them here

SAY-PERSON
CL-USER> (say-person "John") ;some examples
"John"
CL-USER> (say-person "john doe")
"John Doe"
CL-USER> (say-person "john doe" :number "JR")
"John Doe Jr"
CL-USER> (say-person "john doe" :number "Junior")
"John Doe Junior"
CL-USER> (say-person "john doe" :number 1)
"John Doe I"
CL-USER> (say-person "john doe" :number 1 :roman-number nil) ;this is wrong
"John Doe First"
CL-USER> (defun say-person (name &key (number 1 number-p)
                                      (title nil) (roman-number t))
       (let ((number (if number-p
                 (typecase number
                   (integer
                (format nil (if roman-number " ~:@r" " the ~:(~:r~)") number))
                   (otherwise
                (format nil " ~:(~a~)" number)))
                 ""))
         (title (if title 
                (format nil "~:(~a~) " title)
                "")))
         (format nil "~a~:(~a~)~a" title name number)))
WARNING: redefining COMMON-LISP-USER::SAY-PERSON in DEFUN
SAY-PERSON
CL-USER> (say-person "john doe" :number 1 :roman-number nil) ;thats better
"John Doe the First"
CL-USER> (say-person "louis" :title "king" :number 16 :roman-number nil)
"King Louis the Sixteenth"
CL-USER> (say-person "louis" :title "king" :number 16 :roman-number t)
"King Louis XVI"
CL-USER> (defun hello (&optional (name "World") &rest arguments) ;now we will just
       (apply #'hello-name name arguments)) ;pass all arguments to hello-name
WARNING: redefining COMMON-LISP-USER::HELLO in DEFUN
HELLO
CL-USER> (defun hello-name (name &rest arguments) ;which will now just use
       (format t "Hello, ~a!" (apply #'say-person name arguments))) ;say-person
WARNING: redefining COMMON-LISP-USER::HELLO-NAME in DEFUN
HELLO-NAME
CL-USER> (hello "louis" :title "king" :number 16) ;this works now
Hello, King Louis XVI!
NIL
CL-USER>

이것은 Common Lisp의 format 기능의 고급 기능과 선택적 매개 변수 및 키워드 인수 (예 :number )와 같은 일부 기능을 강조 표시합니다. 이것은 또한 공통 리스프에서 REPL에서 대화 형 개발의 예를 보여줍니다.

REPL의 간단한 Hello World 프로그램

Common Lisp REPL은 대화 형 환경입니다. 프롬프트 후에 작성된 모든 양식이 평가되고 그 값은 나중에 평가 결과로 인쇄됩니다. Common Lisp에서 가장 간단한 가능한 "Hello, World!"프로그램은 다음과 같습니다.

CL-USER> "Hello, World!"
"Hello, World!"
CL-USER>

여기서 발생하는 것은 string costant가 REPL의 입력으로 주어지며, 평가되고 결과가 인쇄됩니다. 이 예제에서 볼 수있는 것은 숫자와 같은 문자열, NILT 와 같은 특수 기호 및 몇 가지 다른 리터럴은 자체 평가 형식인데, 즉 자체 평가할 수 있습니다.

기본 표현식

REPL에서 몇 가지 기본 표현식을 사용해 봅시다.

CL-USER> (+ 1 2 3)
6
CL-USER> (- 3 1 1)
1
CL-USER> (- 3)
-3
CL-USER> (+ 5.3 (- 3 2) (* 2 2))
10.3
CL-USER> (concatenate 'string "Hello, " "World!")
"Hello, World!"
CL-USER> 

Common Lisp 프로그램의 기본 구성 요소는 양식 입니다. 이 예제에서 우리는 첫 번째 요소가 연산자 (또는 함수)이고 나머지 요소가 피연산자 ( "접두사 표기법"또는 "폴란드어 표기법") 인 목록으로 작성된 표현식 인 함수 형식 을 갖습니다 "). REPL에 서식을 쓰면 평가가됩니다. 예제에서는 인수가 상수, 문자열 및 기호 인 유형 (유형의 이름 인 'string 의 경우)이있는 간단한 표현식을 볼 수 있습니다. 산술 연산자가 여러 가지 인수를 취할 수 있음을 알 수 있습니다.

괄호는 구문에서 없어서는 안될 부분이므로 다른 프로그래밍 언어처럼 자유롭게 사용할 수 없습니다. 예를 들어, 다음은 오류입니다.

(+ 5 ((+ 2 4)))
> Error: Car of ((+ 2 4)) is not a function name or lambda-expression. ...

Common Lisp에서는 데이터, 기호, 매크로 형식, 특수 형식 및 람다 형식을 사용할 수 있습니다. 그것들은 평가되거나, 0, 하나 또는 그 이상의 값을 반환하도록 작성되거나, 매크로에 입력되어 다른 형태로 변환 될 수 있습니다.

정수 목록 합계

(defun sum-list-integers (list)
    (reduce '+ list))

; 10
(sum-list-integers '(1 2 3 4))

; 55
(sum-list-integers '(1 2 3 4 5 6 7 8 9 10))

람다 식과 익명 함수

무명 함수람다 식 (Lambda Expression)을 통해 이름없이 정의 될 수 있습니다. 이러한 유형의 함수를 정의 할 때는 키워드 defun 대신 키워드 lambda 가 사용됩니다. 다음 줄은 모두 동등하며 두 숫자의 합을 출력하는 익명 함수를 정의합니다.

(lambda (x y) (+ x y))
(function (lambda (x y) (+ x y)))
#'(lambda (x y) (+ x y))

생성시 그 유용성은 현저하게 람다 형태 즉, 리스트 형태 인 첫 번째 요소는 람다 식이고 나머지 요소 익명 함수의 인수 어디. 예 ( 온라인 실행 ) :

(print ((lambda (x y) (+ x y)) 1 2)) ; >> 3

(print (mapcar (lambda (x y) (+ x y)) '(1 2 3) '(2 -5 0))) ; >> (3 -3 3)

Common Lisp 학습 리소스

온라인 도서

온라인에서 자유롭게 액세스 할 수있는 책입니다.

온라인 참고 문헌

오프라인 도서

이것들은 당신이 살 필요가 있거나 도서관에서 빌려줄 책입니다.

온라인 커뮤니티

도서관

미리 패키지화 된 Lisp 환경

이들은 당신이 필요로하는 모든 것이 미리 패키지되고 사전 구성되어 있기 때문에 설치가 쉽고 시작하기 쉬운 리스프 편집 환경입니다.

  • Portacle 은 이식성 있고 다중 플랫폼 인 Common Lisp 환경입니다. Slime, SBCL (인기있는 Common Lisp 구현), Quicklisp 및 Git을 사용하여 약간 사용자 정의 된 Emacs를 제공합니다. 설치가 필요하지 않으므로 이동하는 데 매우 빠르고 쉬운 방법입니다.
  • Lispbox 는 Windows, Mac OSX 및 Linux 용 아카이브로 미리 패키지화 된 IDE (Emacs + SLIME), Common Lisp 환경 (Clozure Common Lisp) 및 라이브러리 관리자 (Quicklisp)입니다. "Lisp in a Box"의 후손 실용적인 Common Lisp 책에서 추천.
  • 미리 포장되어 있지는 않지만 SLIM 은 Emacs를 Common Lisp IDE로 바꾸고 사용자 가 시작하도록 도와주는 사용자 설명서 가 있습니다. 별도의 Common Lisp 구현이 필요합니다.

일반적인 Lisp 구현

이 절에서는 몇 가지 일반적인 CL 구현과 해당 설명서를 나열합니다. 달리 명시하지 않는 한, 이들은 자유 소프트웨어 구현입니다. Cliki의 자유 소프트웨어 Common Lisp Implementations 목록Wikipedia의 상용 Common Lisp 구현 목록을 참조하십시오.