common-lisp Handledning
Komma igång med vanlig-lisp
Sök…
Anmärkningar
Detta är en enkel hej världsfunktion i Common Lisp. Exempel kommer att skriva ut texten Hello, World!
(utan citattecken, följt av en ny linje) till standardutgången.
Common Lisp är ett programmeringsspråk som till stor del används interaktivt med ett gränssnitt känt som en REPL. Med REPL (Read Eval Print Loop) kan man skriva kod, få den utvärderad (kör) och se resultaten omedelbart. Frågan om REPL (vid vilken punkt man anger koden som ska köras) indikeras av CL-USER>
. Ibland kommer något annat än CL-USER
att visas före >
men detta är fortfarande en REPL.
Efter prompten kommer en kod, vanligtvis antingen ett enda ord (dvs ett variabelnamn) eller ett formulär (en lista med ord / formulär som är bifogade mellan (
och )
) (dvs. ett funktionssamtal eller deklaration, etc). På nästa rad kommer alla utskrifter som programmet skriver ut (eller ingenting om programmet skriver ut ingenting) och sedan värdena som returneras genom att utvärdera uttrycket. Normalt returnerar ett uttryck ett värde men om det returnerar flera värden visas de en gång per rad.
versioner
Version | Utgivningsdatum |
---|---|
Vanliga Lisp | 1984/01/01 |
ANSI Common Lisp | 1994-01-01 |
Hej världen
Följande är ett utdrag från en REPL-session med Common Lisp där en "Hej, världen!" funktion definieras och körs. Se kommentarerna längst ner på denna sida för en mer ingående beskrivning av en REPL.
CL-USER> (defun hello ()
(format t "Hello, World!~%"))
HELLO
CL-USER> (hello)
Hello, World!
NIL
CL-USER>
Detta definierar "funktionen" för nollargument som heter hello
, som kommer att skriva strängen "Hello, World!"
följt av en ny linje till standardutdata och returnera NIL
.
För att definiera en funktion skriver vi
(defun name (parameters...)
code...)
I detta fall kallas funktionen hello
, tar inga parametrar och koden den kör är att göra ett funktionssamtal. Det returnerade värdet från en lisp-funktion är den sista bitkoden i funktionen som körs så hello
returnerar vad som helst (format t "Hello, World!~%")
Returnerar.
I lisp för att ringa en funktion skriver man (function-name arguments...)
där function-name
är namnet på funktionen och arguments...
är den (mellanseparerade) listan med argument till samtalet. Det finns några speciella fall som ser ut som funktionssamtal men till exempel, i koden ovan finns det ingen defun
funktion som blir anropad, den behandlas speciellt och definierar en funktion istället.
Vid den andra uppmaningen till REPL, efter att vi har definierat hello
, kallar vi den utan parametrar genom att skriva (hello)
. Detta kallar i sin tur format
med parametrarna t
och "Hello, World!~%"
. format
producerar formaterad utmatning baserad på de argument som den ges (lite som en avancerad version av printf
i C). Det första argumentet berättar var det ska matas ut till, med t
betyder standardutgång. Det andra argumentet berättar vad man ska skriva ut (och hur man tolkar eventuella extra parametrar). Direktivet (specialkod i det andra argumentet) ~%
berättar för formatet att skriva ut en ny linje (dvs. på UNIX kan det skriva \n
och på windows \r\n
). Format returnerar vanligtvis NIL
(lite som NULL
på andra språk).
Efter den andra prompten ser vi att Hello, World
har skrivits ut och på nästa rad att det returnerade värdet var NIL
.
Hej, namn
Detta är ett lite mer avancerat exempel som visar några fler funktioner hos vanlig lisp. Vi börjar med en enkel Hello, World!
fungera och demonstrera viss interaktiv utveckling på REPL. Observera att all text från en semikolon ;
, till resten av raden är en kommentar.
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>
Detta belyser några av de avancerade funktionerna i Common Lisps format
såväl som vissa funktioner som valfria parametrar och nyckelordargument (t.ex. :number
). Detta ger också ett exempel på interaktiv utveckling hos en REPL i vanlig lisp.
Det enkla Hello World-programmet i REPL
Common Lisp REPL är en interaktiv miljö. Varje formulär som skrivs efter prompten utvärderas och dess värde skrivs ut efteråt som resultat av utvärderingen. Så det enklaste möjliga "Hej, världen!" programmet i Common Lisp är:
CL-USER> "Hello, World!"
"Hello, World!"
CL-USER>
Vad som händer här är att en strängkostant ges i input till REPL, den utvärderas och resultatet skrivs ut. Det som kan ses av detta exempel är att strängar, som nummer, speciella symboler som NIL
och T
och några få andra bokstäver, är självutvärderande former: det vill säga de utvärderar för sig själva.
Grundläggande uttryck
Låt oss prova några grundläggande uttryck i 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>
Den grundläggande byggstenen i ett Common Lisp-program är formen . I dessa exempel har vi funktionsformer , det vill säga uttryck, skrivna som lista, där det första elementet är en operatör (eller funktion) och resten av elementen är operanderna (detta kallas "Prefix Notation" eller "Polish Notation") ”). Att skriva formulär i REPL orsakar deras utvärdering. I exemplen kan du se enkla uttryck vars argument är konstant antal, strängar och symboler (för 'string
, som är namnet på en typ). Du kan också se att aritmetiska operatörer kan ta valfritt antal argument.
Det är viktigt att notera att parenteser är en integrerad del av syntaxen och inte kan användas fritt som på andra programmeringsspråk. Till exempel är följande ett fel:
(+ 5 ((+ 2 4)))
> Error: Car of ((+ 2 4)) is not a function name or lambda-expression. ...
I Common Lisp-former kan det också vara data, symboler, makroformer, specialformer och lambda-former. De kan skrivas för att utvärderas, returnera noll, ett eller flera värden, eller kan ges i input till ett makro, som transformerar dem i andra former.
Summan av listan över heltal
(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-uttryck och anonyma funktioner
En anonym funktion kan definieras utan namn genom ett Lambda-uttryck . För att definiera denna typ av funktioner används nyckelordet lambda
istället för nyckelordet defun
. Följande rader är alla likvärdiga och definierar anonyma funktioner som matar ut summan av två nummer:
(lambda (x y) (+ x y))
(function (lambda (x y) (+ x y)))
#'(lambda (x y) (+ x y))
Deras användbarhet märks när man skapar Lambda-former , dvs en form som är en lista där det första elementet är lambda-uttrycket och de återstående elementen är den anonyma funktionens argument. Exempel ( exekvering 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)
Vanliga resurser för Lisp Learning
Online-böcker
Det här är böcker som är fritt tillgängliga online.
- Practical Common Lisp av Peter Seibel är en bra introduktion till CL för erfarna programmerare, som försöker lyfta fram från början vad som gör CL annorlunda än andra språk.
- Common Lisp: A Gentle Introduction to Symbolic Computation av David S. Touretzky är en bra introduktion för personer som är nya i programmering.
- Common Lisp: En interaktiv metod av Stuart C. Shapiro användes som en kursbok, och kursanteckningar medföljer boken på webbplatsen.
- Common Lisp, språket av Guy L. Steele är en beskrivning av Common Lisp-språket. Enligt CLiki är den föråldrad, men den innehåller bättre beskrivningar av loopmakro och format än Common Lisp Hyperspec gör.
- On Lisp av Paul Graham är en utmärkt bok för medelupplevda Lispers.
- Let Over Lambda av Doug Hoyte är en avancerad bok om Lisp Macro. Flera personer rekommenderade att du var bekväm med On Lisp innan du läser denna bok, och att starten är långsam.
Referenser online
- Den gemensamma Lisp Hyperspec är språket referensdokument för Common Lisp.
- Common Lisp Cookbook är en lista över användbara Lisp-recept. Innehåller också en lista över andra onlinekällor för CL-information.
- Common Lisp Quick Reference har utskrivbara Lisp-referensblad.
- Lispdoc.com söker efter flera källor till Lisp-information (Praktisk vanlig lisp, framgångsrik Lisp, On Lisp, HyperSpec) för dokumentation.
- L1sp.org är en omdirigeringstjänst för dokumentation.
Offline böcker
Det här är böcker som du antagligen måste köpa eller låna ut från ett bibliotek.
- ANSI Common Lisp av Paul Graham .
- Vanliga Lisp-recept av Edmund Weitz .
- Paradigms of Artificial Intelligence Programming har många intressanta applikationer av Lisp, men är inte någon bra referens för AI längre.
Online-gemenskaper
- CLiki har en bra start-sida . En bra resurs för alla saker CL. Har en omfattande lista över Lisp-böcker .
- Common Lisp subreddit har massor av användbara länkar och referensdokument i sidofältet.
- IRC: #lisp, #ccl, #sbcl och andra på Freenode .
- Common-Lisp.net tillhandahåller värd för många vanliga lisp-projekt och användargrupper.
bibliotek
- Quicklisp är biblioteksansvarig för Common Lisp och har en lång lista över bibliotek som stöds .
- Quickdocs är värd för biblioteksdokumentation för många CL-bibliotek.
- Awesome CL är en samhällsstyrd kuraterad lista över bibliotek, ramverk och andra blanka saker sorterade efter kategori.
Förpackade Lisp-miljöer
Det här är Lisp-redigeringsmiljöer som är lätta att installera och komma igång med eftersom allt du behöver är förpackat och förkonfigurerat.
- Portacle är en bärbar och multiplatform Common Lisp-miljö. Den levererar en anpassad Emacs med Slime, SBCL (en populär Common Lisp-implementering), Quicklisp och Git. Ingen installation behövs, så det är ett mycket snabbt och enkelt sätt att komma igång.
- Lispbox är en IDE (Emacs + SLIME), Common Lisp-miljö (Clozure Common Lisp) och bibliotekshanterare (Quicklisp), förpackade som arkiv för Windows, Mac OSX och Linux. Efterkommande av "Lisp in a Box" Rekommenderas i den praktiska Common Lisp-boken.
- Inte förpackat, men SLIME förvandlar Emacs till en Common Lisp IDE och har en bruksanvisning som hjälper dig att komma igång. Kräver en separat Common Lisp-implementering.
Vanliga Lisp-implementationer
Det här avsnittet listar några vanliga CL-implementationer och deras manualer. Såvida inget annat anges är detta gratis programvaruimplementeringar. Se även Clikis lista över gratis programvara Common Lisp Implementations och Wikipedia's lista över kommersiella Common Lisp Implementations .
- Allegro Common Lisp (ACL) och manual . Kommersiell, men har en gratis Express Edition och träningsfilmer på Youtube .
- CLISP och manual .
- Clozure Common Lisp (CCL) och manual .
- Carnegie Mellon University Common Lisp (CMUCL) , har en manual och annan användbar informationssida .
- Embeddable Common Lisp (ECL) och manual .
- LispWorks och manual . Kommersiell, men har en personlig utgåva med vissa begränsningar .
- Steel Bank Common Lisp (SBCL) och manual .
- Scieneer Common Lisp (SCL) och manual är en kommersiell implementering av Linux och Unix, men har en obegränsad gratis utvärdering och icke-kommersiell användning .