common-lisp Samouczek
Rozpoczęcie pracy z common-lisp
Szukaj…
Uwagi
Jest to prosta funkcja Witaj świecie w Common Lisp. Przykłady wydrukują tekst Hello, World!
(bez cudzysłowu; po nim nowy wiersz) na standardowe wyjście.
Common Lisp to język programowania, który jest w dużej mierze wykorzystywany interaktywnie przy użyciu interfejsu znanego jako REPL. REPL (Read Eval Print Loop) pozwala wpisać kod, poddać go ocenie (uruchomić) i natychmiast zobaczyć wyniki. Monit o REPL (w którym momencie należy wpisać kod do uruchomienia) jest oznaczony przez CL-USER>
. Czasami przed >
pojawi się coś innego niż CL-USER
, ale nadal jest to REPL.
Po pytaniu pojawia się kod, zwykle albo pojedyncze słowo (tj. Nazwa zmiennej), albo formularz (lista słów / formularzy zamkniętych między (
i )
) (tj. Wywołanie funkcji lub deklaracja itp.). W następnym wierszu będzie każde wyjście, które program wypisuje (lub nic, jeśli program nic nie wypisuje), a następnie wartości zwracane przez ocenę wyrażenia. Zwykle wyrażenie zwraca jedną wartość, ale jeśli zwraca wiele wartości, pojawiają się raz na linię.
Wersje
Wersja | Data wydania |
---|---|
Common Lisp | 1984-01-01 |
ANSI Common Lisp | 01.01.1994 |
Witaj świecie
Poniżej znajduje się fragment sesji REPL z Common Lisp, w której „Witaj, świecie!” funkcja jest zdefiniowana i wykonana. Zobacz uwagi na dole tej strony, aby uzyskać dokładniejszy opis REPL.
CL-USER> (defun hello ()
(format t "Hello, World!~%"))
HELLO
CL-USER> (hello)
Hello, World!
NIL
CL-USER>
Definiuje to „funkcję” zerowych argumentów o nazwie hello
, która zapisze ciąg "Hello, World!"
po którym następuje nowa linia na standardowe wyjście i zwraca NIL
.
Aby zdefiniować funkcję, piszemy
(defun name (parameters...)
code...)
W tym przypadku funkcja nazywa się hello
, nie przyjmuje parametrów, a uruchamiany przez nią kod wykonuje jedno wywołanie funkcji. Zwrócona wartość z funkcji lisp jest ostatnim bitem kodu w funkcji do uruchomienia, więc hello
zwraca cokolwiek (format t "Hello, World!~%")
Zwraca.
W lisp do wywołania funkcji zapisuje się (function-name arguments...)
gdzie function-name
to nazwa funkcji, a arguments...
to (oddzielona spacjami) lista argumentów wywołania. Istnieją specjalne przypadki, które wyglądają jak wywołania funkcji, ale na przykład w powyższym kodzie nie ma wywoływanej funkcji defun
, jest ona traktowana specjalnie i zamiast niej definiuje funkcję.
W drugim monicie REPL, po zdefiniowaniu funkcji hello
, wywołujemy ją bez parametrów, pisząc (hello)
. To z kolei wywoła funkcję format
z parametrami t
"Hello, World!~%"
. format
funkcja produkuje wyjście sformatowaną w oparciu o argumenty, które jest przekazywana (trochę jak zaawansowana wersja printf
w C). Pierwszy argument mówi mu, do którego wyjścia, t
oznacza standardowe wyjście. Drugi argument mówi mu, co wydrukować (i jak interpretować dodatkowe parametry). Dyrektywa (specjalny kod w drugim argumencie) ~%
mówi formatowi, aby wypisał nowy wiersz (tzn. W UNIX może napisać \n
a w Windows \r\n
). Format zwykle zwraca NIL
(trochę jak NULL
w innych językach).
Po drugim pytaniu widzimy, że Hello, World
został wydrukowany, aw następnym wierszu zwrócona wartość to NIL
.
Cześć, imię
Jest to nieco bardziej zaawansowany przykład, który pokazuje kilka dodatkowych cech wspólnego seplenienia. Zaczynamy od prostego Hello, World!
funkcjonować i zademonstrować interaktywny rozwój na REPL. Zauważ, że dowolny tekst z średnika ;
, do końca linii jest komentarz.
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>
Podkreśla to niektóre zaawansowane funkcje funkcji format
Common Lisp, a także niektóre funkcje, takie jak parametry opcjonalne i argumenty słów kluczowych (np . :number
). Daje to również przykład interaktywnego rozwoju na REPL we wspólnym seplenieniu.
Prosty program Hello World w REPL
Common Lisp REPL to środowisko interaktywne. Każdy formularz napisany po pytaniu jest oceniany, a jego wartość jest następnie drukowana w wyniku oceny. Więc najprostsze możliwe „Witaj, świecie!” program w Common Lisp to:
CL-USER> "Hello, World!"
"Hello, World!"
CL-USER>
To, co się tutaj dzieje, polega na tym, że łańcuch wejściowy jest podawany do REPL, jest analizowany, a wynik jest drukowany. Z tego przykładu widać, że ciągi znaków, takie jak liczby, specjalne symbole, takie jak NIL
i T
oraz kilka innych literałów, są formami samooceny : to znaczy oceniają je same.
Podstawowe wyrażenia
Wypróbujmy podstawowe wyrażenie w 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>
Podstawowym elementem składowym programu Common Lisp jest forma . W tych przykładach mamy formularze funkcji , czyli wyrażenia zapisane jako lista, w których pierwszym elementem jest operator (lub funkcja), a pozostałe elementy to operandy (to się nazywa „Notacja przedrostka” lub „Notacja polska” ”). Pisanie formularzy w REPL powoduje ich ocenę. W przykładach można zobaczyć proste wyrażenia, których argumentami są stałe liczby, ciągi znaków i symbole (w przypadku 'string
, który jest nazwą typu). Widać również, że operatory arytmetyczne mogą przyjmować dowolną liczbę argumentów.
Należy zauważyć, że nawiasy są integralną częścią składni i nie mogą być używane swobodnie, jak w innych językach programowania. Na przykład następujący błąd:
(+ 5 ((+ 2 4)))
> Error: Car of ((+ 2 4)) is not a function name or lambda-expression. ...
We wspólnych formularzach Lisp mogą być również dane, symbole, formularze makro, formularze specjalne i formularze lambda. Mogą być zapisywane do oceny, zwracając zero, jedną lub więcej wartości, lub mogą być podawane w danych wejściowych do makra, które przekształcają je w inne formy.
Suma listy liczb całkowitych
(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))
Wyrażenia lambda i funkcje anonimowe
Anonimową funkcję można zdefiniować bez nazwy poprzez wyrażenie lambda . Do zdefiniowania tego typu funkcji używa się słowa kluczowego lambda
zamiast słowa kluczowego defun
. Wszystkie poniższe wiersze są równoważne i definiują anonimowe funkcje, które generują sumę dwóch liczb:
(lambda (x y) (+ x y))
(function (lambda (x y) (+ x y)))
#'(lambda (x y) (+ x y))
Ich użyteczność jest zauważalna przy tworzeniu formularzy Lambda , tj. Formularzy, które są listą, w której pierwszym elementem jest wyrażenie lambda, a pozostałe elementy to argumenty funkcji anonimowej. Przykłady ( wykonanie online ):
(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)
Wspólne zasoby edukacyjne Lisp
Książki online
Są to książki ogólnodostępne online.
- Practical Common Lisp autorstwa Petera Seibela to dobre wprowadzenie do CL dla doświadczonych programistów, którzy od samego początku starają się podkreślić, czym różni się CL od innych języków.
- Common Lisp: Delikatne wprowadzenie do symbolicznego obliczenia Davida S. Touretzky'ego to dobre wprowadzenie dla osób początkujących w programowaniu.
- Common Lisp: Interaktywne podejście Stuarta C. Shapiro zostało użyte jako podręcznik kursu, a notatki z kursu towarzyszą książce na stronie internetowej.
- Common Lisp, język autorstwa Guy L. Steele to opis języka Common Lisp. Według CLiki jest on przestarzały, ale zawiera lepsze opisy makra i formatu pętli niż Common Lisp Hyperspec.
- On Lisp Paula Grahama to świetna książka dla średnio doświadczonych Lispers.
- Let Over Lambda autorstwa Douga Hoyte'a to zaawansowana książka o Lisp Macros. Kilka osób zaleciło , abyś przed czytaniem tej książki czuł się komfortowo z On Lisp, i że początek jest wolny.
Referencje online
- Common Lisp Hyperspec jest dokumentem referencyjnym języka Common Lisp.
- Wspólna książka kucharska Lisp to lista przydatnych przepisów Lisp. Zawiera także listę innych internetowych źródeł informacji CL.
- Common Lisp Quick Reference ma drukowane arkusze referencyjne Lisp.
- Lispdoc.com przeszukuje kilka źródeł informacji Lisp (Practical Common Lisp, Successful Lisp, On Lisp, HyperSpec) w poszukiwaniu dokumentacji.
- L1sp.org to usługa przekierowywania dokumentacji.
Książki offline
Są to książki, które prawdopodobnie będziesz musiał kupić lub wypożyczyć w bibliotece.
- ANSI Common Lisp autorstwa Paula Grahama .
- Wspólne przepisy Lisp autorstwa Edmunda Weitza .
- Paradygmaty programowania sztucznej inteligencji mają wiele interesujących zastosowań Lisp, ale nie są już dobrym punktem odniesienia dla AI.
Społeczności internetowe
- CLiki ma świetną stronę Pierwsze kroki . Świetny zasób dla wszystkich rzeczy CL. Ma obszerną listę książek Lisp .
- Wspólny podreddit Lisp zawiera mnóstwo przydatnych linków i dokumentów referencyjnych na pasku bocznym.
- IRC: #lisp, #ccl, #sbcl i inne na Freenode .
- Common-Lisp.net zapewnia hosting wielu popularnych projektów i grup użytkowników.
Biblioteki
- Quicklisp jest menedżerem bibliotek dla Common Lisp i ma długą listę obsługiwanych bibliotek .
- Quickdocs obsługuje dokumentację bibliotek dla wielu bibliotek CL.
- Awesome CL to kierowana przez społeczność wyselekcjonowana lista bibliotek, ram i innych lśniących rzeczy posortowanych według kategorii.
Wstępnie zapakowane środowiska Lisp
Są to środowiska edycyjne Lisp, które są łatwe do zainstalowania i rozpoczęcia, ponieważ wszystko, czego potrzebujesz, jest wstępnie spakowane i wstępnie skonfigurowane.
- Portacle to przenośne i wieloplatformowe środowisko Common Lisp. Dostarcza nieco spersonalizowanych Emacsa ze Slime, SBCL (popularną implementacją Common Lisp), Quicklisp i Git. Nie wymaga instalacji, więc jest to bardzo szybki i łatwy sposób na rozpoczęcie pracy.
- Lispbox to IDE (Emacs + SLIME), środowisko Common Lisp (Clozure Common Lisp) i menedżer bibliotek (Quicklisp), wstępnie spakowane jako archiwa dla systemów Windows, Mac OSX i Linux. Potomek „Lisp in a Box” zalecany w książce Practical Common Lisp.
- Nie jest fabrycznie zapakowany, ale SLIME zmienia Emacsa w Common Lisp IDE i ma instrukcję obsługi, która pomoże ci zacząć. Wymaga osobnej implementacji Common Lisp.
Typowe implementacje Lisp
W tej sekcji wymieniono niektóre typowe implementacje języka CL i ich instrukcje. O ile nie zaznaczono inaczej, są to implementacje wolnego oprogramowania. Zobacz także listę darmowego oprogramowania Common Lisp Implementacje Cliki oraz listę komercyjnych komercyjnych implementacji Common Lisp .
- Allegro Common Lisp (ACL) i podręcznik . Reklama, ale ma bezpłatną wersję Express Edition i filmy szkoleniowe na Youtube .
- CLISP i instrukcja obsługi .
- Clozure Common Lisp (CCL) i instrukcja .
- Carnegie Mellon University Common Lisp (CMUCL) , ma instrukcję i inne przydatne informacje .
- Osadzany Common Lisp (ECL) i instrukcja .
- LispWorks i podręcznik . Komercyjny, ale ma Personal Edition z pewnymi ograniczeniami .
- Steel Bank Common Lisp (SBCL) i podręcznik .
- Scieneer Common Lisp (SCL) i instrukcja to komercyjne wdrożenie Linux i Unix, ale ma nieograniczony bezpłatny ocenę i niekomercyjnych wersję użytkowania .