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.

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.

Online-gemenskaper

bibliotek

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 .



Modified text is an extract of the original Stack Overflow Documentation
Licensierat under CC BY-SA 3.0
Inte anslutet till Stack Overflow