Provided by:
manpages-pl_20060617-3_all 
NAZWA
lisp-tut - Wskazowki dla Common LISP
OPIS
Uwaga: to wprowadzenie do Common Lisp zostalo napisane dla rodowiska
CMU, wic niektore fragmenty pracy z lispem mog si troch roni w ronych
miejscach.
Inne r'od/la informacji
Najlepsza ksika o LISP, ktor znam, to
Guy L. Steele Jr. _Common LISP: the Language_. Digital Press. 1984.
Pierwsza edycja jest latwiejsza do czytania; druga opisuje troch nowszy
standard. (Ronice midzy standardami nie powinny sprawia ronic zwyklym
programistom).
Polecano mi rownie ksik Dave'a Touretsky'ego, cho nie czytalem jej i
nie mog o niej nic powiedzie.
Symbole
Symbol to lacuch znakow. Istniej ograniczenia co do tego, co mona
wstawi do symbolu i co moe by pierwszym znakiem, lecz tak dlugo jak
uywasz prostych liter, cyfr i mylnikow, nic si nie stanie. (Poza tym,
e jeli uywasz tylko cyfr i prawdopodobnie pocztkowego mylnika, to LISP
moe pomyle, e to liczba calkowita, a nie symbol.) Przyklady symboli:
a
b
c1
foo
bar
baaz-quux-garply
Dalej przedstawiamy kilka rzeczy, ktore mona zrobi z symbolami. (Rzeczy
po znaku zachty ">" s tym, co naley wstuka do interpretera LISP,
podczas gdy inne rzeczy s odpowiedziami, drukowanymi przez LISP. Znak
";" jest LISP-owym znakiem komentarza: wszystko od ";" do koca linii
jest ignorowane.
> (setq a 5) ;zachowaj liczb jako warto symbolu
5
> a ;pobierz warto symbolu
5
> (let ((a 6)) a) ;przywi tymczasowo warto symbolu do 6
6
> a ;po zakoczeniu let, warto wraca do 5
5
> (+ a 6) ;uyj wartoci symbolu jako argumentu funkcji
11
> b ;sprobuj pobra warto symbolu, ktory nie ma wartoci
Error: Attempt to take the value of the unbound symbol B
Istniej dwa symbole specjalne, `t' i `nil'. Warto `t' jest zdefiniowana
zawsze jako `t', a warto `nil' jest zdefiniowana zawsze jako `nil'.
LISP uywa `t' i `nil' do reprezentowania prawdy i falszu. Przykladowe
uycie, opisane dokladniej dalej:
> (if t 5 6)
5
> (if nil 5 6)
6
> (if 4 5 6)
5
Ostatni przyklad jest cudaczny, lecz prawidlowy: `nil' oznacza falsz, a
wszystko inne oznacza prawd. (O ile nie mamy potrzeby robi inaczej,
uywamy t do oznaczania prawdy, tak dla czystej prostoty.)
Symbole takie jak `t' i `nil' s nazywane samorozwijajcymi, poniewa
rozwijaj si same na siebie. Istnieje cala klasa samorozwijajcych si
symboli, zwanych slowami kluczowymi; dowolny symbol, ktorego nazwa
rozpoczyna si od dwukropka jest slowem kluczowym. (Zobacz niej
przyklady zastosowa slow kluczowych.) Przyklady:
> :this-is-a-keyword
:THIS-IS-A-KEYWORD
> :so-is-this
:SO-IS-THIS
> :me-too
:ME-TOO
Liczby
Liczba ca/lkowita jest lacuchem cyfr, opcjonalnie poprzedzonych + lub -.
Liczba rzeczywista wyglda jak liczba calkowita, lecz ma kropk dziesitn
i moe by zapisana w notacji naukowej. Liczba wymierna wyglda jak dwie
liczby calkowite z kresk ulamkow / midzy nimi. LISP obsluguje te
liczbyzespolone, ktore s zapisywane jako #c(r i) (gdzie r jest czci
rzeczywist, a i jest czci urojon). Liczb jest dowolny zapis z
powyszych. Przyklady:
5
17
-34
+6
3.1415
1.722e-15
#c(1.722e-15 0.75)
Standardowe funkcje arytmetyczne s wci dostpne: +, -, *, /, floor,
ceiling, mod, sin, cos, tan, sqrt, exp, expt, itd. Wszystkie one
przyjmuj dowolny rodzaj argumentu. +, -, * i / zwracaj liczb zgodnie z
nastpujcymi zasadami: liczba calkowita plus wymierna daje wymiern,
wymierna plus rzeczywist daje rzeczywist, a rzeczywista plus zespolona
daje zespolon. Oto przyklady:
> (+ 3 3/4) ;determinacja typu wynikowego
15/4
> (exp 1) ;e
2.7182817
> (exp 3) ;e*e*e
20.085537
> (expt 3 4.2) ;potga o podstawie innej ni e
100.90418
> (+ 5 6 7 (* 8 9 10)) ;funkcje +-*/ przyjmuj argumenty wielokrotne
Nie ma ogranicze w absolutnej wartoci liczby calkowitej, poza rozmiarem
pamici komputera. Ostrzegam jednak, e obliczenia na duych liczbach mog
by wolne. (Podobnie jak obliczenia na liczbach wymiernych, szczegolnie
w porownaniu do oblicze na malych liczbach calkowitych lub
rzeczywistych.)
Wagoniki (ang. conses)
Wagonik jest zwyklym dwuelementowym rekordem. Z przyczyn historycznych
jego pola s nazywane "car" i "cdr". (Na pierwszej maszynie, na ktorej
zaimplementowano LISP istnialy dwie instrukcje, CAR i CDR, ktore
oznaczaly "contents of address register" i "contents of decrement
register". Wagoniki byly zaimplementowane przy uyciu tych rejestrow.)
Wagoniki s latwe w uyciu:
> (cons 4 5) ;Zaalokuj wagonik. Ustaw car na 4 a cdr na 5.
(4 . 5)
> (cons (cons 4 5) 6)
((4 . 5) . 6)
> (car (cons 4 5))
4
> (cdr (cons 4 5))
5
Listy
Z wagonikow mona budowa wiele struktur. Pewnie najprostsz jest lista
powizana: car kadego wagonika wskazuje na jeden z elementow listy, a
cdr albo na nastpny element, albo na nil. Moesz stworzy tak powizan
list przy uyciu funkcji list:
> (list 4 5 6)
(4 5 6)
Zauwa, e LISP drukuje powizane listy w szczegolny sposob: pomija
niektore kropki i nawiasy. Zasada jest taka: jeli cdr wagonika to nil,
LISP nie drukuje kropki, ani nil; jeli cdr wagonika A to wagonik B, to
nie drukuje kropki dla wagonika A, ani nawiasow dla wagonika B. Wic:
> (cons 4 nil)
(4)
> (cons 4 (cons 5 6))
(4 5 . 6)
> (cons 4 (cons 5 (cons 6 nil)))
(4 5 6)
Ostatni przyklad jest rownowany dokladnie wywolaniu (list 4 5 6).
Zauwa, e nil oznacza teraz list bez elementow: cdr listy 2 elementowej
(a b) to (b), lista o jednym elemencie; cdr 1 elementowego (b) to nil,
ktory jest list bez elementow.
Pusty (nil) car i cdr jest definiowany jako `nil'.
Jeli zapisujesz swoj list w zmiennej, moesz spowodowa, e bdzie dziala
jak stos:
> (setq a nil)
NIL
> (push 4 a)
(4)
> (push 5 a)
(5 4)
> (pop a)
5
> a
(4)
> (pop a)
4
> (pop a)
NIL
> a
NIL
Funkcje
Powyej byl przyklad funkcji. Oto kilka innych:
> (+ 3 4 5 6) ;ta funkcja pobiera dowoln liczb argumentow
18
> (+ (+ 3 4) (+ (+ 4 5) 6)) ;czy notacja przedrostkowa nie jest super?
22
> (defun foo (x y) (+ x y 5)) ;definiowanie funkcji
FOO
> (foo 5 0) ;wolanie funkcji
10
> (defun fact (x) ;funkcja rekursywna
(if (> x 0)
(* x (fact (- x 1)))
1
) )
FACT
> (fact 5)
120
> (defun a (x) (if (= x 0) t (b (- x)))) ;funkcje wzajemnie rekurencyjne
A
> (defun b (x) (if (> x 0) (a (- x 1)) (a (+ x 1))))
B
> (a 5)
T
> (defun bar (x) ;funkcja o wielu instrukcjach w swoim
(setq x (* x 3)) ;ciele -- zwroci warto, zwracan przez
(setq x (/ x 2)) ;jej ostatni instrukcj
(+ x 4)
)
BAR
> (bar 6)
13
Gdy zdefiniowalimy `foo', nadalimy mu dwa argumenty, `x' i `y'. Teraz,
gdy wolamy `foo', musimy poda dokladnie dwa argumenty: pierwszy stanie
si na czas wywolania wartoci `x', a drugi stanie si wartoci `y'. W
lispie wikszo zmiennych jest zawona leksykalnie; to znaczy jeli `foo'
wola `bar', a `bar' probuje odnie si do `x', to nie jest to moliwe.
Proces przyznawania symbolowi wartoci na czas zawe leksykalnych jest
nazywany wizaniem (binding).
Dla swoich funkcji moesz podawa argumenty dodatkowe. Kady argument po
symbolu &optional jest opcjonalny:
> (defun bar (x &optional y) (if y x 0))
BAR
> (defun baaz (&optional (x 3) (z 10)) (+ x z))
BAAZ
> (bar 5)
0
> (bar 5 t)
5
> (baaz 5)
15
> (baaz 5 6)
11
> (baaz)
13
Funkcj `bar' mona wywola z jednym lub dwoma argumentami. Po wywolaniu z
jednym argumentem, warto `x' jest ustawiana normalnie, natomiast `y'
jest ustawiane na `nil'. Po wywolaniu z dwoma argumentami, warto `x' i
`y' zostanie odpowiednio nimi zainicjalizowana.
Funkcja `baaz' ma dwa argumenty opcjonalne. Dla kadego z nich daje
warto domyln: jeli wolajcy poda tylko jeden argument, `z' zostanie
zwizane nie z `nil', lecz z 10, a gdy wolajcy w ogole nie poda
argumentow, `x' zostanie powizany z 3, a `z' z 10.
Moesz spowodowa, e funkcja przyjmuje dowoln liczb argumentow, koczc jej
argument parametrem &rest. LISP wtedy zbierze wszystkie argumenty do
listy i przywie j do parametru &rest.
> (defun foo (x &rest y) y)
FOO
> (foo 3)
NIL
> (foo 4 5 6)
(5 6)
W kocu, moesz poda swojej funkcji dowolny rodzaj argumentu
opcjonalnego, zwanego argumentem s/lowa kluczowego. Wolajcy moe podawa
takie argumenty w dowolnej kolejnoci--s one etykietowane slowami
kluczowymi.
> (defun foo (&key x y) (cons x y))
FOO
> (foo :x 5 :y 3)
(5 . 3)
> (foo :y 3 :x 5)
(5 . 3)
> (foo :y 3)
(NIL . 3)
> (foo)
(NIL)
Parametr &key moe mie rownie warto domyln:
> (defun foo (&key (x 5)) x)
FOO
> (foo :x 7)
7
> (foo)
5
Drukowanie
Niektore funkcje mog przesyla dane na wyjcie. Najprostsz jest print,
ktora drukuje swoj argument i zwraca go.
> (print 3)
3
3
Pierwsze 3 zostalo wydrukowane, drugie zwrocone.
Jeli oczekujesz bardziej zloonego wyjcia, musisz uy formatu. Oto
przyklad:
> (format t "An atom: ~S~%and a list: ~S~%and an integer: ~D~%"
nil (list 5) 6)
An atom: NIL
and a list: (5)
and an integer: 6
Pierwszy argument instrukcji format to `t', `nil' lub strumie. `T'
wskazuje na wyjcie na terminal. `Nil' oznacza, e niczego nie mona
drukowa, a naley zamiast tego powroci do lacucha zawierajcego wyjcie.
Strumienie s ogolnymi miejscami przeplywu wyjcia: wskazuj na pliki,
terminale lub inne programy. Ten podrcznik nie bdzie si dokladniej
zajmowal strumieniami.
Kolejnym argumentem jest matryca formatujca, ktora jest lacuchem
opcjonalnie zawierajcym dyrektywy formatujce.
Wszystkie pozostale argumenty mog by uywane przez dyrektywy formatujce.
LISP zamieni dyrektywy na odpowiednie znaki, w oparciu argumenty, do
ktorych (dyrektywy) si one odnosz. Nastpnie lacuch zostanie
wydrukowany.
Format zawsze zwraca `nil', chyba e jego pierwszym argumentem jest
`nil'--wtedy nic nie drukuje i zwraca lacuch.
W powyszym przykladzie istniej trzy rone dyrektywy: ~S, ~D i ~%.
Pierwsza przyjmuje dowolny obiekt LISP i jest zamieniana drukowaln
reprezentacj tego obiektu (tak sam, jak produkowana przez print).
Druga przyjmuje tylko liczby calkowite. Ostatnia nie odnosi si do
argumentu. Jest zawsze zamieniana na powrot karetki.
Inn przydatn dyrektyw jest ~~, ktora jest zamieniana na pojedyncz `~'.
Zajrzyj do podrcznika LISP, s tam rone inne dyrektywy formatujce.
Formy i ptla g/l'owna
Wszystko, co wpisujesz do interpretera LISP okrelane jest mianem form;
interpreter odczytuje tak form, analizuje j i drukuje wynik. Procedura
ta jest nazywana ptl odczytu-analizy-drukowania.
Niektore formy mog dawa bldy. Po bldzie, LISP przerzuci ci do
debuggera, aby mogl znale bld. Kady debugger LISP jest inny; jednak
wikszo z nich odpowiada na komend "help" lub ":help".
Ogolnie, form jest zarowno atom (np. symbol, liczba calkowita, lacuch)
jak lista. Jeli forma jest atomem, LISP analizuje j natychmiast. Jeli
jest list, to jej pierwszy element jest traktowany jak nazwa funkcji;
pozostale elementy analizowane s rekurencyjnie i wywoluje si t funkcj z
wartociami pozostalych elementow jako argumentami.
Na przyklad, jeli LISP widzi form (+ 3 4), traktuje `+' jako nazw
funkcji. Potem analizuje 3 aby pobra 3 i 4 aby pobra 4; w kocu wola `+'
z argumentami 3 i 4. Funkcja `+' zwraca 7, co jest drukowane jako
wynik.
Ptla glowna daje inne udogodnienia; szczegolnie wygodn rzecz jest
moliwo mowienia o wynikach poprzednio wpisanych form. LISP zawsze
udostpnia swoje trzy najwiesze wyniki; kryj si one pod symbolami *, **
i ***. Na przyklad:
> 3
3
> 4
4
> 5
5
> ***
3
> ***
4
> ***
5
> **
4
> *
4
Formy specjalne
Istnieje pewna liczba form specjalnych, ktore wygldaj jak wywolania
funkcji, lecz nimi nie s. Zaliczaj si do nich konstrukcje sterujce,
takie jak instrukcje if i ptle do; przypisania takie jak setq, setf,
push i pop; definicje takie, jak defunidefstruct; a take konstrukcje
wice, takie jak let. (Nie wszystkie te formy zostaly ju wymienione.
Patrz niej.)
Jedn przydatn form specjaln jest forma cytowania (quote): chroni ona
argument przed zanalizowaniem. Na przyklad:
> (setq a 3)
3
> a
3
> (quote a)
A
> 'a ;'a jest skrotem dla (quote a)
A
Inn prost form specjaln jest forma funkcji (function): powoduje, e jej
argument jest interpretowany jako funkcja:
> (setq + 3)
3
> +
3
> '+
+
> (function +)
#<Function + @ #x-fbef9de>
> #'+ ;#'+ jest skrotem dla (function +)
#<Function + @ #x-fbef9de>
Ta forma specjalna jest przydatna gdy chcesz przekaza funkcj jako
argument do innej funkcji. Niej s przyklady funkcji, biorcych argumenty
funkcyjne.
Wizanie
Wizanie to zawone leksykalnie przypisanie. Zachodzi na zmiennych w
licie parametrow funkcji za kadym wywolaniem funkcji: formalne
parametry s wizane do rzeczywistych parametrow na czas wywolania
funkcji. Zmienne mona wiza w dowolnym miejscu programu, uywajc
specjalnej formy let, ktora wyglda tak:
(let ((var1 val1)
(var2 val2)
...
)
body
)
`Let' wie `var1' do `val1' i `var2' do `val2' (i tak dalej); potem
wykonuje instrukcje swojego ciala. Cialo `let' podpada pod dokladnie te
same reguly, co cialo funkcji. Przyklady:
> (let ((a 3)) (+ a 1))
4
> (let ((a 2)
(b 3)
(c 0))
(setq c (+ a b))
c
)
5
> (setq c 4)
4
> (let ((c 5)) c)
5
> c
4
Zamiast (let ((a nil) (b nil)) ...), moesz napisa (let (a b) ...).
`Val1', `val2', itd. wewntrz `let' nie mog odnosi si do zmiennych
`var1', `var2', itd., ktore s wizane. Na przyklad
> (let ((x 1)
(y (+ x 1)))
y
)
Error: Attempt to take the value of the unbound symbol X
Jeli symbol `x' ju ma warto globaln, wynikiem bd dziwne zdarzenia:
> (setq x 7)
7
> (let ((x 1)
(y (+ x 1)))
y
)
8
Forma specjalna let* jest podobna do `let', lecz zezwala wartociom na
wskazywanie na zmienne, zdefiniowane w `let' wczeniej. Na przyklad:
> (setq x 7)
7
> (let* ((x 1)
(y (+ x 1)))
y
)
2
Forma
(let* ((x a)
(y b))
...
)
jest rownowana
(let ((x a))
(let ((y b))
...
) )
Zakresy dynamiczne
Formy `let' i `let*' daj zawanie leksykalne, ktore jest rzecz, do
ktorej mogle si przyzwyczai w C lub Pascalu. Zakresy (zawanie)
dynamiczne s popularne w BASIC-u: jeli przypiszesz warto zmiennej
dynamicznej, kade wspomnienie tej zmiennej zwraca nadan warto, a nie
przyznasz nowej.
W LISP-ie, zmienne dynamicznego zakresu s nazywane zmiennymi
specjalnymi. Moesz je deklarowa w formie defvar. Oto przyklady
zmiennych dynamicznie i leksykalnie zawanych.
W tym przykladzie, funkcja `check-regular' odnosi si do zmiennej
`regular' (np. leksykalnej). Poniewa `check-regular' jest leksykalnie
poza `let', ktory wie `regular', `check-regular' zwraca globaln warto
zmiennej.
> (setq regular 5)
5
> (defun check-regular () regular)
CHECK-REGULAR
> (check-regular)
5
> (let ((regular 6)) (check-regular))
5
W tym przykladzie, funkcja `check-special' odnosi si do zmiennej
`special' (np. dynamicznie zawonej). Poniewa wywolanie `check-special'
jest tymczasowo wewntrz `let', ktory wie `special', `check-special'
zwraca lokaln warto zmiennej.
> (defvar *special* 5)
*SPECIAL*
> (defun check-special () *special*)
CHECK-SPECIAL
> (check-special)
5
> (let ((*special* 6)) (check-special))
6
Tradycyjnie, nazwa zmiennej specjalnej rozpoczyna si od `*'. Zmienne
specjalne s uywane glownie jako zmienne globalne, gdy programici
zazwyczaj oczekuj dla zmiennych lokalnych zawania leksykalnego, a dla
globalnych dynamicznego.
Dla dalszych informacji o ronicach midzy zaweniami leksykalnymi i
dynamicznymi, zobacz Common LISP: the Language.
Tablice
Funkcja make-array tworzy tablic. Funkcja aref daje dostp do jej
elementow. Wszystkie elementy tablicy s pocztkowo ustawione na `nil'.
Na przyklad:
> (make-array '(3 3))
#2a((NIL NIL NIL) (NIL NIL NIL) (NIL NIL NIL))
> (aref * 1 1)
NIL
> (make-array 4) ;tablice 1D nie wymagaj dodatkowych nawiasow
#(NIL NIL NIL NIL)
Indeksy tablic zawsze rozpoczynaj si od 0.
Jak ustawia elementy tablicy, opisano niej.
Napisy
Napis jest sekwencj znakow w podwojnych cudzyslowach. W LISP napis jest
reprezentowany jako tablica znakow o zmiennej dlugoci. Napis zawierajcy
podwojne cudzyslowy mona zapisa, poprzedzajc cudzyslow znakiem lewego
ukonika; podwojny lewy ukonik oznacza pojedynczy lewy ukonik. Na
przyklad:
"abcd" ma 4 znaki
"\"" ma 1 znak
"\\" ma 1 znak
Oto kilka funkcji zajmujcych si napisami:
> (concatenate 'string "abcd" "efg")
"abcdefg"
> (char "abc" 1)
#\b ;LISP zapisuje znaki poprzedzone #\
> (aref "abc" 1)
#\b ;pamitaj, napisy w rzeczywistoci s tablicami
Funkcja concatenate moe w rzeczywistoci dziala z dowolnym rodzajem
sekwencji:
> (concatenate 'string '(#\a #\b) '(#\c))
"abc"
> (concatenate 'list "abc" "de")
(#\a #\b #\c #\d #\e)
> (concatenate 'vector '#(3 3 3) '#(3 3 3))
#(3 3 3 3 3 3)
Struktury
Struktury LISP s analogiczne do struktur C lub rekordow Pascala. Oto
przyklad:
> (defstruct foo
bar
baaz
quux
)
FOO
Przyklad ten definiuje typ danych o nazwie `foo', ktory jest struktur,
zawierajc 3 pola. Definiuje te 4 funkcje, ktore operuj na tym typie
danych: make-foo, foo-bar, foo-baaz i foo-quux. Pierwsza tworzy nowy
obiekt typu `foo'; pozostale daj dostp do poszczegolnych pol obiektu.
Oto jak uywa tych funkcji:
> (make-foo)
#s(FOO :BAR NIL :BAAZ NIL :QUUX NIL)
> (make-foo :baaz 3)
#s(FOO :BAR NIL :BAAZ 3 :QUUX NIL)
> (foo-bar *)
NIL
> (foo-baaz **)
3
Funkcja `make-foo' moe pobiera argument slowa kluczowego dla kadego
pola struktury `foo'. Funkcje dostpu do pol pobieraj jeden argument,
struktur typu `foo' i zwracaj odpowiedni warto.
Zobacz niej jak ustawi pola struktury.
Setf
Pewne formy w LISP-ie naturalnie definiuj pozycj w pamici. Na przyklad,
jeli warto `x' jest struktur typu `foo', to (foo-bar x) definiuje pole
`bar' o wartoci `x'. Lub jeli warto `y' jest jednowymiarow tablic,
(aref y 2) definiuje trzeci element `y'.
Specjalna forma setf uywa swojego pierwszego argumentu do zdefiniowania
miejsca w pamici, analizuje drugi argument i zapisuje wynik w wynikowej
pozycji pamici. Na przyklad,
> (setq a (make-array 3))
#(NIL NIL NIL)
> (aref a 1)
NIL
> (setf (aref a 1) 3)
3
> a
#(NIL 3 NIL)
> (aref a 1)
3
> (defstruct foo bar)
FOO
> (setq a (make-foo))
#s(FOO :BAR NIL)
> (foo-bar a)
NIL
> (setf (foo-bar a) 3)
3
> a
#s(FOO :BAR 3)
> (foo-bar a)
3
Setf jest jedynym sposobem na ustawianie pol struktury lub tablicy.
Oto kilka innych przykladow setf i zwizanych z nim funkcji.
> (setf a (make-array 1)) ;setf na zmiennej jest rownowane setq
#(NIL)
> (push 5 (aref a 1)) ;push moe dziala jak setf
(5)
> (pop (aref a 1)) ;podobnie pop
5
> (setf (aref a 1) 5)
5
> (incf (aref a 1)) ;incf odczytuje z danego miejsca,
6 ;inkrementuje i zapisuje z powrotem.
> (aref a 1)
6
Zmienne logiczne i warunki
LISP do oznaczania falszu uywa symbolu `nil'. Wszystko inne ni `nil'
oznacza prawd. O ile nie mamy specjalnych powodow, dla prawdy uywa si
symbolu `t'.
LISP daje standardowy zestaw funkcji logicznych, np. and, or i not.
And i or s blisko-zwierajce: and nie zanalizuje adnych argumentow na
prawo od pierwszego zrozumianego jako nil, a or nie zanalizuje adnych
argumentow na prawo od pierwszego, zrozumianego jako t.
LISP daje te specjalne formy dla wyrae warunkowych. Najprostsz jest if.
Pierwszy argument tej formy okrela czy wywola argument drugi, czy
trzeci.
> (if t 5 6)
5
> (if nil 5 6)
6
> (if 4 5 6)
5
Jeli potrzebujesz wicej ni jednej instrukcji w klauzuli then lub else
if'a, to moesz uy specjalnej formy progn. Progn wykonuje kad instrukcj
swojego ciala i zwraca ostatni warto.
> (setq a 7)
7
> (setq b 0)
0
> (setq c 5)
5
> (if (> a 5)
(progn
(setq a (+ b 7))
(setq b (+ c 8)))
(setq b 4)
)
13
Instrukcja if, ktorej brak klauzuli then lub else, moe by zapisana przy
uyciu specjalnej formy unless:
> (when t 3)
3
> (when nil 3)
NIL
> (unless t 3)
NIL
> (unless nil 3)
3
When i unless w przeciwiestwie do if, zezwalaj na dowoln liczb
instrukcji w swoich cialach. (Np. (when x a b c) jest rownowane (if x
(progn a b c)).
> (when t
(setq a 5)
(+ a 6)
)
11
Bardziej zloone warunki mona definiujc przy uyciu formy specjalnej cond
ktora jest rownowana konstrukcji if ... else if .. fi.
Cond sklada si z symbolu `cond', za ktorym nastpuj klauzule cond, z
ktorych kada jest list. Pierwszy element klauzuli cond jest warunkiem;
pozostale elementy (jeli istniej) s akcj. Forma cond szuka pierwszej
klauzuli, ktorej warunek jest spelniony; potem wykonuje odpowiedni akcj
i zwraca warto wynikow. aden pozostaly warunek nie jest ju analizowany;
nie s te wykonywane inne akcje ni ta, odpowiadajca warunkowi. Na
przyklad:
> (setq a 3)
3
> (cond
((evenp a) a) ;jeli a jest parzyste, zwro a
((> a 7) (/ a 2)) ;inaczej, jeli a jest > ni 7, zwro a/2
((< a 5) (- a 1)) ;inaczej, jeli a jest < ni 5, zwro a-1
(t 17) ;inaczej zwro 17
)
2
Jeli w danej klauzuli cond brakuje akcji, cond zwraca warto, do ktorej
zostal zredukowany warunek:
> (cond ((+ 3 4)))
7
Oto mala sprytna rekurencyjna funkcja, uywajca cond. Moesz sprobowa
udowodni, e koczy si dla wszystkich liczb calkowitych x wielkoci
przynajmniej 1. (Jeli ci si uda, opublikuj rezultat.)
> (defun hotpo (x steps) ;hotpo oznacza Half Or Triple Plus One
(cond
((= x 1) steps)
((oddp x) (hotpo (+ 1 (* x 3)) (+ 1 steps)))
(t (hotpo (/ x 2) (+ 1 steps)))
) )
A
> (hotpo 7 0)
16
Instrukcja case w LISP jest podobna do instrukcji switch w C:
> (setq x 'b)
B
> (case x
(a 5)
((d e) 7)
((b f) 3)
(otherwise 9)
)
3
Klauzula otherwise oznacza, e jeli x nie jest a, b, d, e lub f,
instrukcja case ma zwroci 9.
Iteracja
Najprostsz konstrukcj iteracyjn w LISP jest ptla (loop): konstrukcja ta
kolejno wykonuje swoje ciala, a nie natrafi na specjaln form return. Na
przyklad
> (setq a 4)
4
> (loop
(setq a (+ a 1))
(when (> a 7) (return a))
)
8
> (loop
(setq a (- a 1))
(when (< a 3) (return))
)
NIL
Kolejn najprostsz jest dolist: wie ona zmienn do elementow listy w
kolejnoci i koczy gdy trafi na koniec listy.
> (dolist (x '(a b c)) (print x))
A
B
C
NIL
Dolist zawsze zwraca `nil'. Zauwa, e warto `x' w powyszym przykladzie
nigdy nie byla `nil': NIL znajdujcy si po C byl wartoci zwracan przez
dolist, drukowan przez ptl odczytu-analizy-drukowania.
Najbardziej skomplikowanym rodzajem iteracji jest do. Instrukcja do
wyglda nastpujco:
> (do ((x 1 (+ x 1))
(y 1 (* y 2)))
((> x 5) y)
(print y)
(print 'working)
)
1
WORKING
2
WORKING
4
WORKING
8
WORKING
16
WORKING
32
Pierwsza cz `do' okrela, ktore zmienne naley zwiza, jakie s ich wartoci
pocztkowe i jak je odwiea. Nastpna cz okrela warunek zakoczenia i warto
zwracan. Ostatni czci jest cialo. Forma do wie jak `let' swoje zmienne
do wartoci pocztkowych, a potem sprawdza warunek zakocznia. Dopoki
warunek jest falszywy, wykonuje cialo; gdy warunek staje si prawdziwy,
zwraca warto formy return-value.
Forma do* jest analogiczna do `let*' w `let'.
Nielokalne wyjcia
Forma specjalna return, wspomniana w poprzedniej sekcji o iteracji jest
przykladem nielokalnego wyjcia. Innym przykladem jest forma return-
form, ktora zwraca warto z otaczajcej funkcji:
> (defun foo (x)
(return-from foo 3)
x
)
FOO
> (foo 17)
3
Wlaciwie, forma return-form moe zwroci warto z dowolnego nazwanego
bloku--po prostu funkcje s jedynymi blokami, ktore s domylnie nazwane.
Blok nazwany moesz tworzy specjaln form block:
> (block foo
(return-from foo 7)
3
)
7
Forma specjalna return moe zwroci warto z dowolnego bloku o nazwie
`nil'. Domylnie przez nil oznaczane s ptle, lecz moesz te tworzy
wlasne bloki oznaczone `nil':
> (block nil
(return 7)
3
)
7
Inn form, ktora powoduje nielokalne wyjcie jest forma error:
> (error "This is an error")
Error: This is an error
Forma error zalcza format do swoich argumentow, a potem umieszcza ci w
debuggerze.
Funcall, Apply, i Mapcar
Wczeniej obiecalem, e dam troch funkcji, ktore jako argumenty pobieraj
funkcje. Oto one:
> (funcall #'+ 3 4)
7
> (apply #'+ 3 4 '(3 4))
14
> (mapcar #'not '(t nil t nil t nil))
(NIL T NIL T NIL T)
Funcall wola swoj pierwszy argument z pozostalymi argumentami.
Apply dziala podobnie do funcall, lecz jej ostatni argument powinien by
list; elementy tej listy s traktowane tak, jakby byly dodatkowymi
argumentami funcall.
Pierwszy argument mapcar musi by funkcj jednoargumentow; mapcar stosuje
t funkcj do kadego elementu listy i zbiera wyniki w innej licie.
Funcall i apply s uywane czsto gdy ich pierwszym argumentem jest
zmienna. Na przyklad mechanizm przeszukiwania moe bra jako parametr
funkcj heurystyczn i uywa funcall lub apply do wolania jej dla opisu
stanu. Funkcje sortowania, opisane dalej uywaj funcall do wolania
funkcji porownawczych.
Mapcar wraz funkcjami bez nazwy (patrz niej) moe zastpi wiele ptli.
Lambda
Jeli chcesz utworzy funkcj tymczasow i nie chcesz nadawa jej nazwy, to
moesz uy lambda.
> #'(lambda (x) (+ x 3))
(LAMBDA (X) (+ X 3))
> (funcall * 5)
8
Polczenie lambda i mapcar moe zastpi wiele ptli. Na przyklad, nastpujce
postacie s rownowane:
> (do ((x '(1 2 3 4 5) (cdr x))
(y nil))
((null x) (reverse y))
(push (+ (car x) 2) y)
)
(3 4 5 6 7)
> (mapcar #'(lambda (x) (+ x 2)) '(1 2 3 4 5))
(3 4 5 6 7)
Sortowanie
LISP daje do sortowania dwa prymitywy: sort i stable-sort.
> (sort '(2 1 5 4 6) #'<)
(1 2 4 5 6)
> (sort '(2 1 5 4 6) #'>)
(6 5 4 2 1)
Pierwszym argumentem sort jest lista; drugim funkcja porownawcza.
Funkcja sortujca nie gwarantuje stabilnoci: jeli s dwa elementy takie,
e (and (not (< a b)) (not (< b a))) , to sort moe zaaranowa je w
dowolnym porzdku. Funkcja stable-sort jest taka sama jak sort, lecz
gwarantuje, e dwa rownowane elementy pojawi si w licie posortowanej w
tej samej kolejnoci co na licie wejciowej.
Uwaga: sort moe niszczy swoj argument, wic jeli sekwencja wejciowa jest
dla ciebie wana, utworz jej kopi poleceniem copy lub copy-list czy
copy-seq.
R'owno
LISP ma wiele ronych wizji rownoci. Rowno numeryczna jest oznaczana
przez =. Dwa symbole s eq tylko gdy s identyczne. Dwie kopie tej samej
listy nie s eq, cho s rowne.
> (eq 'a 'a)
T
> (eq 'a 'b)
NIL
> (= 3 4)
T
> (eq '(a b c) '(a b c))
NIL
> (equal '(a b c) '(a b c))
T
> (eql 'a 'a)
T
> (eql 3 3)
T
Eql jest rownowany eq dla symboli i = dla liczb.
Equal jest r'ownowany eql dla symboli i liczb. Jest prawdziwy dla dwoch
wagonikow tylko gdy ich car-y i cdr-y s sobie rowne. Jest prawdziwy dla
dwoch struktur tylko gdy wszystkie ich pola s sobie rowne.
Przydatne funkcje listowe
Oto funkcje, dzialajce na listach.
> (append '(1 2 3) '(4 5 6)) ;lcz (konkatenuj) listy
(1 2 3 4 5 6)
> (reverse '(1 2 3)) ;odwro elementy listy
(3 2 1)
> (member 'a '(b d a c)) ;ustaw czlonkowstwo--zwraca pierwszy ogon
(A C) ;w ktorym car jest danym elemetem.
> (find 'a '(b d a c)) ;inny sposob ustawiania czlonkowstwa
A
> (find '(a b) '((a d) (a d e) (a b d e) ()) :test #'subsetp)
(A B D E) ;find jest jednak bardziej elastyczny
> (subsetp '(a b) '(a d e)) ;zawieranie si zbiorow
NIL
> (intersection '(a b c) '(b)) ;przekroj zbiorow
(B)
> (union '(a) '(b)) ;suma zbiorow
(A B)
> (set-difference '(a b) '(a)) ;ronica zbiorow
(B)
Subsetp, intersection, union i set-difference zakladaj, e aden z
argumentow nie posiada zduplikowanych elementow. Np. (subsetp '(a a)
'(a b b)) moe si nie powie.
Find, subsetp, intersection, union i set-difference mog bra argument o
slowie kluczowym :test; domylnie wszystkie uywaj eql.
Pocztki z Emacsem
Do edycji kodu LISP moesz uywa Emacsa: wikszo Emacsow jest
skonfigurowania na wchodzenie w tryb LISP za kadym razem gdy znajd
plik, koczcy si na .lisp. Jeli u ciebie tak si nie dzieje, wpisz M-x
lisp-mode.
Pod Emacsem moesz te uruchamia LISP: upewnij si, e masz w ciece komend
o nazwie lisp, ktora uruchamia twojego ulubionego LISP-a. Na przyklad
moesz wpisa
ln -s /usr/local/bin/clisp ~/bin/lisp
Potem, w Emacsie wpisz M-x run-lisp. Moesz wtedy wysla kod LISP do
interpretera i zrobi wiele innych fajnych rzeczy; dla dalszych
informacji wpisz C-h m z dowolnego bufora w trybie LISP.
W rzeczywistoci nawet nie musisz tworzy dowizania. Emacs ma zmienn o
nazwie inferior-lisp-program; wic jeli dodasz lini
(setq inferior-lisp-program "/usr/local/bin/clisp")
do swojego pliku .emacs, to Emacs bdzie wiedzial gdzie szuka CLISP-a
dla komendy M-x run-lisp.
AUTORZY
Geoffrey J. Gordon <ggordon@cs.cmu.edu> (pitek, 5 lutego 1993).
Poprawione przez Brunona Haible'a <haible@ma2s2.mathematik.uni-
karlsruhe.de>. Przetlumaczone na jzyk polski i przekonwertowane do
postaci man przez Przemka Borysa <pborys@dione.ids.pl>
INFORMACJE O T/LUMACZENIU
Powysze tlumaczenie pochodzi z nieistniejcego ju Projektu Tlumaczenia
Manuali i moe nie by aktualne. W razie zauwaenia ronic midzy powyszym
opisem a rzeczywistym zachowaniem opisywanego programu lub funkcji,
prosimy o zapoznanie si z oryginaln (angielsk) wersj strony podrcznika.
wrzesie 1999 LISP-TUT(5)