common-lisp Tutorial
Iniziare con Common-Lisp
Ricerca…
Osservazioni
Questa è una semplice funzione di ciao mondo in Common Lisp. Gli esempi stamperanno il testo Hello, World!
(senza virgolette, seguito da una nuova riga) per l'output standard.
Common Lisp è un linguaggio di programmazione che è ampiamente utilizzato in modo interattivo utilizzando un'interfaccia nota come REPL. Il REPL (Read Eval Print Loop) consente di digitare il codice, farlo valutare (eseguire) e vedere immediatamente i risultati. Il prompt per REPL (al punto in cui si digita il codice da eseguire) è indicato da CL-USER>
. A volte qualcosa di diverso da CL-USER
apparirà prima del >
ma questo è ancora un REPL.
Dopo il prompt viene fornito un codice, di solito una singola parola (cioè un nome di variabile) o un modulo (un elenco di parole / moduli racchiusi tra (
e )
) (cioè una chiamata di funzione o una dichiarazione, ecc.). Nella riga successiva sarà presente qualsiasi output che il programma stampa (o nulla se il programma non stampa nulla) e quindi i valori restituiti valutando l'espressione. Normalmente un'espressione restituisce un valore ma se restituisce più valori compaiono una volta per riga.
Versioni
Versione | Data di rilascio |
---|---|
Lisp comune | 1984-01-01 |
ANSI Common Lisp | 1994-01-01 |
Ciao mondo
Quello che segue è un estratto da una sessione REPL con Common Lisp in cui un "Hello, World!" la funzione è definita ed eseguita. Vedere le note in fondo a questa pagina per una descrizione più approfondita di un REPL.
CL-USER> (defun hello ()
(format t "Hello, World!~%"))
HELLO
CL-USER> (hello)
Hello, World!
NIL
CL-USER>
Questo definisce la "funzione" di zero argomenti denominata hello
, che scriverà la stringa "Hello, World!"
seguito da una nuova riga sullo standard output e restituire NIL
.
Per definire una funzione scriviamo
(defun name (parameters...)
code...)
In questo caso la funzione è chiamata hello
, non richiede parametri e il codice che esegue è quello di effettuare una chiamata di funzione. Il valore restituito da una funzione lisp è l'ultimo bit di codice nella funzione da eseguire in modo che i ritorni di hello
qualsiasi (format t "Hello, World!~%")
Restituiscano.
In lisp per chiamare una funzione si scrivono (function-name arguments...)
dove function-name
è il nome della funzione e arguments...
è l'elenco degli argomenti (separati da spazi) della chiamata. Ci sono alcuni casi speciali che assomigliano a chiamate di funzioni ma, ad esempio, nel codice precedente non c'è alcuna funzione di defun
che viene chiamata, viene trattata in modo speciale e definisce una funzione.
Al secondo prompt del REPL, dopo aver definito la funzione hello
, la chiamiamo senza parametri scrivendo (hello)
. Questo a sua volta chiamerà il format
funzione con i parametri t
e "Hello, World!~%"
. La funzione format
produce output formattati in base agli argomenti che vengono forniti (un po 'come una versione avanzata di printf
in C). Il primo argomento dice che dove output, con t
che significa standard output. Il secondo argomento indica cosa stampare (e come interpretare eventuali parametri aggiuntivi). La direttiva (codice speciale nel secondo argomento) ~%
indica al formato di stampare una nuova riga (ovvero su UNIX potrebbe scrivere \n
e su windows \r\n
). Il formato di solito restituisce NIL
(un po 'come NULL
in altre lingue).
Dopo il secondo prompt vediamo che Hello, World
è stato stampato e nella riga successiva che il valore restituito era NIL
.
Ciao, nome
Questo è un esempio un po 'più avanzato che mostra alcune altre funzionalità di Common Lisp. Iniziamo con un semplice Hello, World!
funzione e dimostrare alcuni sviluppi interattivi al REPL. Si noti che qualsiasi testo da un punto e virgola ;
, per il resto della linea è un commento.
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>
Questo evidenzia alcune delle funzioni avanzate della funzione di format
del Common Lisp e alcune funzioni come parametri opzionali e argomenti di parole chiave (es . :number
). Questo dà anche un esempio di sviluppo interattivo a un REPL in comune lisp.
Il semplice programma Hello World in REPL
Common Lisp REPL è un ambiente interattivo. Ogni modulo scritto dopo il prompt viene valutato e il suo valore viene stampato in seguito come risultato della valutazione. Quindi il programma "Hello, World!" Più semplice possibile in Common Lisp è:
CL-USER> "Hello, World!"
"Hello, World!"
CL-USER>
Quello che succede qui è che una stringa costante viene data in input al REPL, viene valutata e il risultato viene stampato. Ciò che si può vedere da questo esempio è che le stringhe, come i numeri, i simboli speciali come NIL
e T
e alcuni altri letterali, sono forme di auto-valutazione : cioè valutano se stessi.
Espressioni di base
Proviamo alcune espressioni di base nella 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>
Il modulo base di un programma Common Lisp è la forma . In questi esempi abbiamo forme di funzioni , cioè espressioni, scritte come lista, in cui il primo elemento è un operatore (o funzione) e il resto degli elementi sono gli operandi (questo è chiamato "Notazione prefisso" o "Notazione polacca" “). La scrittura di moduli nel REPL causa la loro valutazione. Negli esempi è possibile visualizzare espressioni semplici i cui argomenti sono numeri, stringhe e simboli costanti (nel caso di 'string
, che è il nome di un tipo). Puoi anche vedere che gli operatori aritmetici possono prendere qualsiasi numero di argomenti.
È importante notare che le parentesi sono parte integrante della sintassi e non possono essere utilizzate liberamente come in altri linguaggi di programmazione. Ad esempio il seguente è un errore:
(+ 5 ((+ 2 4)))
> Error: Car of ((+ 2 4)) is not a function name or lambda-expression. ...
Nelle forme comuni di Lisp possono essere anche dati, simboli, forme macro, forme speciali e forme lambda. Possono essere scritti per essere valutati, restituendo zero, uno o più valori, oppure possono essere dati in input a una macro, che li trasforma in altre forme.
Somma dell'elenco di numeri interi
(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))
Espressioni lambda e funzioni anonime
Una funzione anonima può essere definita senza un nome attraverso un'espressione Lambda . Per definire questo tipo di funzioni, viene utilizzata la parola chiave lambda
posto della parola chiave defun
. Le seguenti righe sono tutte equivalenti e definiscono funzioni anonime che generano la somma di due numeri:
(lambda (x y) (+ x y))
(function (lambda (x y) (+ x y)))
#'(lambda (x y) (+ x y))
La loro utilità è evidente quando si creano forme Lambda , cioè una forma che è una lista in cui il primo elemento è l'espressione lambda e gli elementi rimanenti sono gli argomenti della funzione anonima. Esempi ( esecuzione 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)
Risorse di apprendimento Lisp comuni
Libri online
Questi sono libri che sono liberamente accessibili online.
- Practical Common Lisp di Peter Seibel è una buona introduzione a CL per i programmatori esperti, che cerca di evidenziare fin dall'inizio ciò che rende il CL diverso dalle altre lingue.
- Common Lisp: A Gentle Introduzione al calcolo simbolico di David S. Touretzky è una buona introduzione per chi è nuovo alla programmazione.
- Common Lisp: un approccio interattivo di Stuart C. Shapiro è stato utilizzato come libro di testo del corso e le note del corso accompagnano il libro sul sito web.
- Common Lisp, the Language di Guy L. Steele è una descrizione del linguaggio Common Lisp. Secondo il CLiki è obsoleto, ma contiene descrizioni migliori della macro e del formato del ciclo rispetto a Common Lisp Hyperspec.
- On Lisp di Paul Graham è un ottimo libro per Lispers di livello intermedio.
- Let Over Lambda di Doug Hoyte è un libro avanzato su Lisp Macro. Diverse persone consigliano di sentirsi a proprio agio con On Lisp prima di leggere questo libro e che l'avvio è lento.
Riferimenti online
- Common Lisp Hyperspec è il documento di riferimento della lingua per Common Lisp.
- The Common Lisp Cookbook è un elenco di utili ricette Lisp. Contiene anche un elenco di altre fonti online di informazioni CL.
- Riferimento rapido Lisp comune ha fogli di riferimento Lisp stampabili.
- Lispdoc.com ricerca diverse fonti di informazioni Lisp (Practical Common Lisp, Success Lisp, On Lisp, HyperSpec) per la documentazione.
- L1sp.org è un servizio di reindirizzamento per la documentazione.
Libri offline
Questi sono libri che probabilmente dovrai acquistare o prestare da una biblioteca.
- ANSI Common Lisp di Paul Graham .
- Ricette Lisp comuni di Edmund Weitz .
- Paradigmi di Intelligenza Artificiale La programmazione ha molte interessanti applicazioni di Lisp, ma non è più un buon riferimento per l'intelligenza artificiale.
Comunità online
- Il CLiki ha un'ottima pagina introduttiva . Una grande risorsa per tutte le cose CL. Ha una lunga lista di libri Lisp .
- Common Lisp subreddit ha un sacco di link utili e documenti di riferimento nella barra laterale.
- IRC: #lisp, #ccl, #sbcl e altri su Freenode .
- Common-Lisp.net fornisce hosting per molti progetti e gruppi di utenti comuni .
biblioteche
- Quicklisp è un gestore di libreria per Common Lisp e ha una lunga lista di librerie supportate .
- Quickdocs ospita la documentazione della libreria per molte librerie CL.
- Awesome CL è un elenco di librerie, framework e altre cose lucide guidate dalla comunità, ordinate per categoria.
Ambienti Lisp preconfezionati
Si tratta di ambienti di editing Lisp facili da installare e da utilizzare poiché tutto ciò di cui si ha bisogno è preconfigurato e preconfigurato.
- Portacle è un ambiente Lisp comune portatile e multipiattaforma. Viene fornito un Emacs leggermente personalizzato con Slime, SBCL (un'implementazione Common Common Lisp), Quicklisp e Git. Nessuna installazione necessaria, quindi è un modo molto semplice e veloce per iniziare.
- Lispbox è un IDE (Emacs + SLIME), un ambiente Common Lisp (Clozure Common Lisp) e un gestore di libreria (Quicklisp), pre-confezionato come archivi per Windows, Mac OSX e Linux. Discendente di "Lisp in a Box" Consigliato nel libro Practical Common Lisp.
- Non pre-confezionato, ma SLIME trasforma Emacs in un IDE Lisp comune e ha un manuale utente per aiutarti a iniziare. Richiede un'implementazione Common Lisp separata.
Implementazioni comuni di Lisp
Questa sezione elenca alcune implementazioni CL comuni e i relativi manuali. Salvo diversa indicazione, si tratta di implementazioni di software libero. Vedi anche l' elenco di Cliki delle implementazioni comuni di Lisp del software libero e l'elenco di Wikipedia delle implementazioni comuni di Lisp comuni .
- Allegro Common Lisp (ACL) e manuale . Commerciale, ma ha una Express Edition gratuita e video di formazione su Youtube .
- CLISP e manuale .
- Clozure Common Lisp (CCL) e manuale .
- Carnegie Mellon University Common Lisp (CMUCL) , ha un manuale e altre informazioni utili .
- Common Lisp (ECL) e manuale incorporabili .
- LispWorks e manuale . Commerciale, ma ha un'edizione personale con alcune limitazioni .
- Steel Bank Common Lisp (SBCL) e manuale .
- Scieneer Common Lisp (SCL) e manual è un'implementazione commerciale Linux e Unix, ma ha una versione gratuita senza valutazione e versione non commerciale .