Provided by: manpages-pl_20051117-1_all bug

NAZWA

       lisp-tut - Wskazówki dla Common LISP

OPIS

       Uwaga:  to  wprowadzenie do Common Lisp zostało napisane dla środowiska
       CMU, więc niektóre fragmenty pracy z lispem mogą się  trochę  różnić  w
       różnych miejscach.

Inne źródła informacji

       Najlepsza książka o LISP, którą znam, to

       Guy L. Steele Jr. _Common LISP: the Language_. Digital Press. 1984.

       Pierwsza  edycja  jest  łatwiejsza  do  czytania;  druga opisuje trochę
       nowszy standard.  (Różnice  między  standardami  nie  powinny  sprawiać
       różnic zwykłym programistom).

       Polecano mi również książkę Dave'a Touretsky'ego, choć nie czytałem jej
       i nie mogę o niej nic powiedzieć.

Symbole

       Symbol to łańcuch znaków. Istnieją ograniczenia co do  tego,  co  można
       wstawić  do symbolu i co może być pierwszym znakiem, lecz tak długo jak
       używasz prostych liter, cyfr i myślników, nic się  nie  stanie.   (Poza
       tym,   że  jeśli  używasz  tylko  cyfr  i  prawdopodobnie  początkowego
       myślnika, to LISP może pomyśleć, że to liczba całkowita, a nie symbol.)
       Przykłady symboli:

               a
               b
               c1
               foo
               bar
               baaz-quux-garply

       Dalej  przedstawiamy  kilka  rzeczy,  które  można  zrobić z symbolami.
       (Rzeczy po znaku zachęty ">" są tym, co należy wstukać do  interpretera
       LISP, podczas gdy inne rzeczy są odpowiedziami, drukowanymi przez LISP.
       Znak ";" jest LISP-owym znakiem komentarza: wszystko od  ";"  do  końca
       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 zakończeniu let, wartość wraca do 5
       5
       > (+ a 6)            ;użyj wartości symbolu jako argumentu funkcji
       11
       > b                  ;spróbuj pobrać wartość symbolu, który nie ma wartości
       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 używa `t' i `nil' do reprezentowania prawdy i fałszu.
       Przykładowe użycie, opisane dokładniej dalej:

       > (if t 5 6)
       5
       > (if nil 5 6)
       6
       > (if 4 5 6)
       5

       Ostatni przykład jest cudaczny, lecz prawidłowy: `nil' oznacza fałsz, a
       wszystko  inne  oznacza prawdę. (O ile nie mamy potrzeby robić inaczej,
       używamy t do oznaczania prawdy, tak dla czystej prostoty.)

       Symbole takie jak `t' i `nil' są nazywane  samorozwijającymi,  ponieważ
       rozwijają się same na siebie. Istnieje cała klasa samorozwijających się
       symboli, zwanych słowami  kluczowymi;  dowolny  symbol,  którego  nazwa
       rozpoczyna  się  od  dwukropka  jest  słowem  kluczowym.  (Zobacz niżej
       przykłady zastosowań słów kluczowych.) Przykłady:

       > :this-is-a-keyword
       :THIS-IS-A-KEYWORD
       > :so-is-this
       :SO-IS-THIS
       > :me-too
       :ME-TOO

Liczby

       Liczba całkowita jest łańcuchem cyfr, opcjonalnie poprzedzonych  +  lub
       -.   Liczba  rzeczywista  wygląda  jak liczba całkowita, lecz ma kropkę
       dziesiętną i może być zapisana w  notacji  naukowej.   Liczba  wymierna
       wygląda jak dwie liczby całkowite z kreską ułamkową / między nimi. LISP
       obsługuje też liczbyzespolone, które są zapisywane jako #c(r i)  (gdzie
       r  jest  częścią  rzeczywistą,  a  i jest częścią urojoną). Liczbą jest
       dowolny zapis z powyższych. Przykłady:

               5
               17
               -34
               +6
               3.1415
               1.722e-15
               #c(1.722e-15 0.75)

       Standardowe funkcje arytmetyczne są wciąż dostępne: +, -, *, /,  floor,
       ceiling,  mod,  sin,  cos,  tan,  sqrt,  exp, expt, itd.  Wszystkie one
       przyjmują dowolny rodzaj argumentu. +, -, * i / zwracają liczbę zgodnie
       z następującymi zasadami: liczba całkowita plus wymierna daje wymierną,
       wymierna  plus  rzeczywistą  daje  rzeczywistą,  a   rzeczywista   plus
       zespolona daje zespoloną. Oto przykłady:

       > (+ 3 3/4)             ;determinacja typu wynikowego
       15/4
       > (exp 1)               ;e
       2.7182817
       > (exp 3)               ;e*e*e
       20.085537
       > (expt 3 4.2)          ;potęga o podstawie innej niż e
       100.90418
       > (+ 5 6 7 (* 8 9 10))  ;funkcje +-*/ przyjmują argumenty wielokrotne

       Nie  ma  ograniczeń  w  absolutnej  wartości  liczby  całkowitej,  poza
       rozmiarem pamięci komputera. Ostrzegam jednak, że obliczenia na  dużych
       liczbach   mogą   być  wolne.  (Podobnie  jak  obliczenia  na  liczbach
       wymiernych, szczególnie w porównaniu do  obliczeń  na  małych  liczbach
       całkowitych lub rzeczywistych.)

Wagoniki (ang. conses)

       Wagonik  jest zwykłym dwuelementowym rekordem. Z przyczyn historycznych
       jego pola są nazywane "car" i "cdr". (Na pierwszej maszynie, na  której
       zaimplementowano  LISP  istniały  dwie  instrukcje,  CAR  i  CDR, które
       oznaczały "contents of  address  register"  i  "contents  of  decrement
       register".  Wagoniki były zaimplementowane przy użyciu tych rejestrów.)

       Wagoniki są łatwe w użyciu:

       > (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 wagoników można budować wiele struktur. Pewnie najprostszą jest lista
       powiązana:  car każdego wagonika wskazuje na jeden z elementów listy, a
       cdr albo na  następny  element,  albo  na  nil.  Możesz  stworzyć  taką
       powiązaną listę przy użyciu funkcji list:

       > (list 4 5 6)
       (4 5 6)

       Zauważ,  że  LISP  drukuje  powiązane listy w szczególny sposób: pomija
       niektóre kropki i nawiasy. Zasada jest taka: jeśli cdr wagonika to nil,
       LISP nie drukuje kropki, ani nil; jeśli cdr wagonika A to wagonik B, to
       nie drukuje kropki dla wagonika A, ani nawiasów dla wagonika B. Więc:

       > (cons 4 nil)
       (4)
       > (cons 4 (cons 5 6))
       (4 5 . 6)
       > (cons 4 (cons 5 (cons 6 nil)))
       (4 5 6)

       Ostatni przykład jest równoważny dokładnie  wywołaniu  (list  4  5  6).
       Zauważ,  że  nil  oznacza  teraz  listę  bez  elementów:  cdr  listy  2
       elementowej (a b) to (b), lista o jednym elemencie; cdr 1  elementowego
       (b) to nil, który jest listą bez elementów.

       Pusty (nil) car i cdr jest definiowany jako `nil'.

       Jeśli  zapisujesz  swoją listę w zmiennej, możesz spowodować, że będzie
       działać 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

       Powyżej był przykład funkcji. Oto kilka innych:

       > (+ 3 4 5 6)                  ;ta funkcja pobiera dowolną liczbę argumentów
       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)                    ;wołanie 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 -- zwróci wartość, zwracaną przez
           (setq x (/ x 2))            ;jej ostatnią instrukcję
           (+ x 4)
         )
       BAR
       > (bar 6)
       13

       Gdy zdefiniowaliśmy `foo', nadaliśmy  mu  dwa  argumenty,  `x'  i  `y'.
       Teraz, gdy wołamy `foo', musimy podać dokładnie dwa argumenty: pierwszy
       stanie się  na  czas  wywołania  wartością  `x',  a  drugi  stanie  się
       wartością `y'.  W lispie większość zmiennych jest zawężona leksykalnie;
       to znaczy jeśli `foo' woła `bar', a `bar' próbuje odnieść się  do  `x',
       to nie jest to możliwe.

       Proces  przyznawania  symbolowi  wartości  na czas zawężeń leksykalnych
       jest nazywany wiązaniem (binding).

       Dla swoich funkcji możesz podawać argumenty dodatkowe.  Każdy  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'  można  wywołać  z  jednym  lub  dwoma  argumentami.  Po
       wywołaniu z jednym argumentem, wartość `x'  jest  ustawiana  normalnie,
       natomiast   `y'   jest   ustawiane  na  `nil'.  Po  wywołaniu  z  dwoma
       argumentami,   wartość   `x'   i   `y'   zostanie   odpowiednio    nimi
       zainicjalizowana.

       Funkcja  `baaz'  ma  dwa  argumenty opcjonalne. Dla każdego z nich daje
       wartość  domyślną:  jeśli  wołający  poda  tylko  jeden  argument,  `z'
       zostanie  związane  nie  z `nil', lecz z 10, a gdy wołający w ogóle nie
       poda argumentów, `x' zostanie powiązany z 3, a `z' z 10.

       Możesz spowodować, że  funkcja  przyjmuje  dowolną  liczbę  argumentów,
       kończąc  jej  argument  parametrem  &rest. LISP wtedy zbierze wszystkie
       argumenty do listy i przywiąże ją do parametru &rest.

       > (defun foo (x &rest y) y)
       FOO
       > (foo 3)
       NIL
       > (foo 4 5 6)
       (5 6)

       W  końcu,  możesz  podać  swojej  funkcji  dowolny   rodzaj   argumentu
       opcjonalnego,  zwanego  argumentem  słowa  kluczowego.   Wołający  może
       podawać takie argumenty  w  dowolnej  kolejności--są  one  etykietowane
       słowami 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 może mieć również wartość domyślną:

       > (defun foo (&key (x 5)) x)
       FOO
       > (foo :x 7)
       7
       > (foo)
       5

Drukowanie

       Niektóre  funkcje  mogą  przesyłać  dane  na  wyjście. Najprostszą jest
       print, która drukuje swój argument i zwraca go.

       > (print 3)
       3
       3

       Pierwsze 3 zostało wydrukowane, drugie zwrócone.

       Jeśli oczekujesz bardziej złożonego wyjścia, musisz użyć  formatu.  Oto
       przykład:

       > (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 wyjście na terminal. `Nil' oznacza, że  niczego  nie  można
       drukować,  a  należy  zamiast  tego  powrócić do łańcucha zawierającego
       wyjście. Strumienie są ogólnymi miejscami przepływu  wyjścia:  wskazują
       na  pliki,  terminale  lub inne programy. Ten podręcznik nie będzie się
       dokładniej zajmował strumieniami.

       Kolejnym argumentem jest  matryca  formatujca,  która  jest  łańcuchem
       opcjonalnie zawierającym dyrektywy formatujące.

       Wszystkie   pozostałe   argumenty  mogą  być  używane  przez  dyrektywy
       formatujące.  LISP zamieni dyrektywy na odpowiednie  znaki,  w  oparciu
       argumenty,  do  których  (dyrektywy) się one odnoszą. Następnie łańcuch
       zostanie wydrukowany.

       Format zawsze zwraca `nil', chyba że  jego  pierwszym  argumentem  jest
       `nil'--wtedy nic nie drukuje i zwraca łańcuch.

       W  powyższym  przykładzie  istnieją  trzy różne 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 całkowite.  Ostatnia  nie  odnosi  się  do
       argumentu.  Jest zawsze zamieniana na powrót karetki.

       Inną  przydatną  dyrektywą jest ~~, która jest zamieniana na pojedynczą
       `~'.

       Zajrzyj do podręcznika LISP, są tam różne inne dyrektywy formatujące.

Formy i pętla główna

       Wszystko, co wpisujesz do interpretera LISP określane jest mianem form;
       interpreter  odczytuje  taką  formę,  analizuje  ją  i  drukuje  wynik.
       Procedura ta jest nazywana pętlą odczytu-analizy-drukowania.

       Niektóre formy mogą dawać błędy. Po  błędzie,  LISP  przerzuci  cię  do
       debuggera,  abyś  mógł  znaleźć  błąd.  Każdy  debugger LISP jest inny;
       jednak większość z nich odpowiada na komendę "help" lub ":help".

       Ogólnie,  formą  jest  zarówno  atom  (np.  symbol,  liczba  całkowita,
       łańcuch)  jak  lista.  Jeśli  forma  jest  atomem,  LISP  analizuje  ją
       natychmiast. Jeśli jest listą, to jej pierwszy element jest  traktowany
       jak  nazwa  funkcji;  pozostałe elementy analizowane są rekurencyjnie i
       wywołuje się  tę  funkcję  z  wartościami  pozostałych  elementów  jako
       argumentami.

       Na  przykład,  jeśli  LISP widzi formę (+ 3 4), traktuje `+' jako nazwę
       funkcji. Potem analizuje 3 aby pobrać 3 i 4 aby pobrać 4; w końcu  woła
       `+'  z  argumentami 3 i 4. Funkcja `+' zwraca 7, co jest drukowane jako
       wynik.

       Pętla główna daje inne udogodnienia; szczególnie  wygodną  rzeczą  jest
       możliwość  mówienia  o  wynikach poprzednio wpisanych form. LISP zawsze
       udostępnia swoje trzy najświeższe wyniki; kryją się one  pod  symbolami
       *, ** i ***. Na przykład:

       > 3
       3
       > 4
       4
       > 5
       5
       > ***
       3
       > ***
       4
       > ***
       5
       > **
       4
       > *
       4

Formy specjalne

       Istnieje  pewna  liczba form specjalnych, które wyglądają jak wywołania
       funkcji, lecz nimi nie są. Zaliczają się do nich konstrukcje sterujące,
       takie  jak  instrukcje if i pętle do; przypisania takie jak setq, setf,
       push i pop; definicje takie, jak defunidefstruct; a  także  konstrukcje
       wiążące, takie jak let. (Nie wszystkie te formy zostały już wymienione.
       Patrz niżej.)

       Jedną przydatną formą specjalną jest forma  cytowania  (quote):  chroni
       ona argument przed zanalizowaniem. Na przykład:

       > (setq a 3)
       3
       > a
       3
       > (quote a)
       A
       > 'a                    ;'a jest skrótem 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 skrótem dla (function +)
       #<Function + @ #x-fbef9de>

       Ta forma specjalna jest przydatna gdy  chcesz  przekazać  funkcję  jako
       argument  do  innej  funkcji.  Niżej  są  przykłady  funkcji, biorących
       argumenty funkcyjne.

Wiązanie

       Wiązanie to zawężone leksykalnie przypisanie. Zachodzi na  zmiennych  w
       liście  parametrów  funkcji  za  każdym  wywołaniem  funkcji:  formalne
       parametry są wiązane do  rzeczywistych  parametrów  na  czas  wywołania
       funkcji.  Zmienne  można  wiązać  w dowolnym miejscu programu, używając
       specjalnej formy let, która wygląda tak:

               (let ((var1 val1)
                     (var2 val2)
                     ...
                    )
                 body
               )

       `Let' wiąże `var1' do `val1' i `var2' do `val2' (i  tak  dalej);  potem
       wykonuje instrukcje swojego ciała. Ciało `let' podpada pod dokładnie te
       same reguły, co ciało funkcji. Przykłady:

       > (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)) ...), możesz napisać (let (a b) ...).

       `Val1', `val2', itd. wewnątrz `let' nie mogą odnosić się  do  zmiennych
       `var1', `var2', itd., które są wiązane. Na przykład

       > (let ((x 1)
               (y (+ x 1)))
           y
         )
       Error: Attempt to take the value of the unbound symbol X

       Jeśli  symbol  `x'  już  ma  wartość  globalną,  wynikiem  będą  dziwne
       zdarzenia:

       > (setq x 7)
       7
       > (let ((x 1)
               (y (+ x 1)))
           y
         )
       8

       Forma specjalna let* jest podobna do `let', lecz zezwala wartościom  na
       wskazywanie na zmienne, zdefiniowane w `let' wcześniej. Na przykład:

       > (setq x 7)
       7
       > (let* ((x 1)
                (y (+ x 1)))
           y
         )
       2

       Forma

               (let* ((x a)
                      (y b))
                 ...
               )

       jest równoważna

               (let ((x a))
                 (let ((y b))
                   ...
               ) )

Zakresy dynamiczne

       Formy  `let'  i `let*' dają zawężanie leksykalne, które jest rzeczą, do
       której mogłeś się przyzwyczaić w C  lub  Pascalu.  Zakresy  (zawężanie)
       dynamiczne  są  popularne w BASIC-u: jeśli przypiszesz wartość zmiennej
       dynamicznej, każde wspomnienie tej zmiennej zwraca nadaną  wartość,  aż
       nie przyznasz nowej.

       W   LISP-ie,   zmienne   dynamicznego  zakresu  są  nazywane  zmiennymi
       specjalnymi.  Możesz je  deklarować  w  formie  defvar.  Oto  przykłady
       zmiennych dynamicznie i leksykalnie zawężanych.

       W  tym  przykładzie,  funkcja  `check-regular'  odnosi  się do zmiennej
       `regular' (np. leksykalnej). Ponieważ `check-regular' jest  leksykalnie
       poza  `let',  który  wiąże  `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 przykładzie,  funkcja  `check-special'  odnosi  się  do  zmiennej
       `special'  (np.   dynamicznie  zawężonej).  Ponieważ  wywołanie `check-
       special' jest tymczasowo wewnątrz `let', który wiąże `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ą używane głównie jako zmienne  globalne,  gdyż  programiści
       zazwyczaj  oczekują  dla  zmiennych lokalnych zawężania leksykalnego, a
       dla globalnych dynamicznego.

       Dla dalszych informacji o różnicach między zawężeniami  leksykalnymi  i
       dynamicznymi, zobacz Common LISP: the Language.

Tablice

       Funkcja  make-array  tworzy  tablicę.  Funkcja  aref daje dostęp do jej
       elementów. Wszystkie elementy tablicy są początkowo ustawione na `nil'.
       Na przykład:

       > (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 nawiasów
       #(NIL NIL NIL NIL)

       Indeksy tablic zawsze rozpoczynają się od 0.

       Jak ustawiać elementy tablicy, opisano niżej.

Napisy

       Napis  jest  sekwencją  znaków  w podwójnych cudzysłowach. W LISP napis
       jest reprezentowany jako tablica  znaków  o  zmiennej  długości.  Napis
       zawierający  podwójne  cudzysłowy można zapisać, poprzedzając cudzysłów
       znakiem lewego ukośnika; podwójny lewy ukośnik oznacza pojedynczy  lewy
       ukośnik. Na przykład:

               "abcd" ma 4 znaki
               "\"" ma 1 znak
               "\\" ma 1 znak

       Oto kilka funkcji zajmujących się napisami:

       > (concatenate 'string "abcd" "efg")
       "abcdefg"
       > (char "abc" 1)
       #\b                     ;LISP zapisuje znaki poprzedzone #\
       > (aref "abc" 1)
       #\b                     ;pamiętaj, napisy w rzeczywistości są tablicami

       Funkcja  concatenate  może w rzeczywistości działać 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 rekordów  Pascala.  Oto
       przykład:

       > (defstruct foo
           bar
           baaz
           quux
         )
       FOO

       Przykład ten definiuje typ danych o nazwie `foo', który jest strukturą,
       zawierającą 3 pola. Definiuje też 4 funkcje, które operują na tym typie
       danych:  make-foo,  foo-bar, foo-baaz i foo-quux.  Pierwsza tworzy nowy
       obiekt typu `foo'; pozostałe dają dostęp do poszczególnych pól obiektu.
       Oto jak używać 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' może pobierać argument słowa kluczowego dla każdego
       pola struktury `foo'. Funkcje dostępu do pól pobierają jeden  argument,
       strukturę typu `foo' i zwracają odpowiednią wartość.

       Zobacz niżej jak ustawić pola struktury.

Setf

       Pewne  formy  w  LISP-ie  naturalnie  definiują  pozycję  w pamięci. Na
       przykład, jeśli wartość `x' jest strukturą typu `foo', to  (foo-bar  x)
       definiuje  pole  `bar'  o  wartości  `x'.  Lub  jeśli  wartość `y' jest
       jednowymiarową tablicą, (aref y 2) definiuje trzeci element `y'.

       Specjalna  forma   setf   używa   swojego   pierwszego   argumentu   do
       zdefiniowania  miejsca  w  pamięci, analizuje drugi argument i zapisuje
       wynik w wynikowej pozycji pamięci. Na przykład,

       > (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 pól struktury lub tablicy.

       Oto kilka innych przykładów setf i związanych z nim funkcji.

       > (setf a (make-array 1))       ;setf na zmiennej jest równoważne setq
       #(NIL)
       > (push 5 (aref a 1))           ;push może działać 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 fałszu używa symbolu `nil'. Wszystko inne niż  `nil'
       oznacza  prawdę.  O  ile nie mamy specjalnych powodów, dla prawdy używa
       się symbolu `t'.

       LISP daje standardowy zestaw funkcji logicznych, np.  and,  or  i  not.
       And i or są blisko-zwierające: and nie zanalizuje żadnych argumentów na
       prawo od pierwszego zrozumianego jako nil, a or nie zanalizuje  żadnych
       argumentów na prawo od pierwszego, zrozumianego jako t.

       LISP daje też specjalne formy dla wyrażeń warunkowych. Najprostszą jest
       if. Pierwszy argument tej formy określa czy wywołać argument drugi, czy
       trzeci.

       > (if t 5 6)
       5
       > (if nil 5 6)
       6
       > (if 4 5 6)
       5

       Jeśli  potrzebujesz  więcej  niż  jednej instrukcji w klauzuli then lub
       else if'a, to możesz użyć specjalnej formy progn.  Progn wykonuje każdą
       instrukcję swojego ciała 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,  której  brak klauzuli then lub else, może być zapisana
       przy użyciu specjalnej formy unless:

       > (when t 3)
       3
       > (when nil 3)
       NIL
       > (unless t 3)
       NIL
       > (unless nil 3)
       3

       When i unless w przeciwieństwie do  if,  zezwalają  na  dowolną  liczbę
       instrukcji  w swoich ciałach. (Np. (when x a b c) jest równoważne (if x
       (progn a b c)).

       > (when t
           (setq a 5)
           (+ a 6)
         )
       11

       Bardziej złożone warunki można definiując przy użyciu formy  specjalnej
       cond która jest równoważna konstrukcji if ... else if .. fi.

       Cond składa się z symbolu `cond', za którym następują  klauzule cond, z
       których  każda  jest  listą.  Pierwszy  element  klauzuli   cond   jest
       warunkiem;  pozostałe  elementy  (jeśli  istnieją) są akcją. Forma cond
       szuka pierwszej klauzuli, której warunek jest spełniony; potem wykonuje
       odpowiednią  akcję  i  zwraca wartość wynikową. Żaden pozostały warunek
       nie jest już analizowany; nie są też  wykonywane  inne  akcje  niż  ta,
       odpowiadająca warunkowi. Na przykład:

       > (setq a 3)
       3
       > (cond
          ((evenp a) a)        ;jeśli a jest parzyste, zwróć a
          ((> a 7) (/ a 2))    ;inaczej, jeśli a jest > niż 7, zwróć a/2
          ((< a 5) (- a 1))    ;inaczej, jeśli a jest < niż 5, zwróć a-1
          (t 17)               ;inaczej zwróć 17
         )
       2

       Jeśli  w  danej  klauzuli  cond  brakuje akcji, cond zwraca wartość, do
       której został zredukowany warunek:

       > (cond ((+ 3 4)))
       7

       Oto mała sprytna rekurencyjna funkcja, używająca cond. Możesz spróbować
       udowodnić,  że  kończy się dla wszystkich liczb całkowitych x wielkości
       przynajmniej 1. (Jeśli 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 jeśli x nie jest  a,  b,  d,  e  lub  f,
       instrukcja case ma zwrócić 9.

Iteracja

       Najprostszą   konstrukcją   iteracyjną   w   LISP  jest  pętla  (loop):
       konstrukcja  ta  kolejno  wykonuje  swoje  ciała,  aż  nie  natrafi  na
       specjalną formę return. Na przykład

       > (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: wiąże ona zmienną do elementów listy w
       kolejności i kończy 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  powyższym
       przykładzie nigdy nie była `nil': NIL znajdujący się po C był wartością
       zwracaną  przez  dolist,   drukowaną   przez   pętlę   odczytu-analizy-
       drukowania.

       Najbardziej  skomplikowanym  rodzajem  iteracji  jest do. Instrukcja do
       wygląda następująco:

       > (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' określa, które zmienne należy związać, jakie są ich
       wartości  początkowe i jak je odświeżać. Następna część określa warunek
       zakończenia i wartość zwracaną. Ostatnią częścią jest ciało.  Forma  do
       wiąże  jak  `let'  swoje  zmienne  do  wartości  początkowych,  a potem
       sprawdza warunek zakończnia. Dopóki  warunek  jest  fałszywy,  wykonuje
       ciało;  gdy  warunek  staje się prawdziwy, zwraca wartość formy return-
       value.

       Forma do* jest analogiczna do `let*' w `let'.

Nielokalne wyjścia

       Forma specjalna return, wspomniana w poprzedniej sekcji o iteracji jest
       przykładem  nielokalnego  wyjścia.  Innym przykładem jest forma return-
       form, która zwraca wartość z otaczającej funkcji:

       > (defun foo (x)
           (return-from foo 3)
           x
         )
       FOO
       > (foo 17)
       3

       Właściwie, forma return-form może zwrócić wartość z dowolnego nazwanego
       bloku--po  prostu  funkcje  są  jedynymi  blokami,  które  są domyślnie
       nazwane.  Blok nazwany możesz tworzyć specjalną formą block:

       > (block foo
           (return-from foo 7)
           3
         )
       7
       Forma specjalna return może zwrócić wartość z dowolnego bloku o  nazwie
       `nil'.  Domyślnie przez nil oznaczane są pętle, lecz możesz też tworzyć
       własne bloki oznaczone `nil':

       > (block nil
           (return 7)
           3
         )
       7

       Inną formą, która powoduje nielokalne wyjście jest forma error:

       > (error "This is an error")
       Error: This is an error

       Forma error załącza format do swoich argumentów, a potem umieszcza  cię
       w debuggerze.

Funcall, Apply, i Mapcar

       Wcześniej  obiecałem,  że  dam  trochę  funkcji,  które  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 woła swój pierwszy argument z pozostałymi argumentami.

       Apply działa podobnie do funcall, lecz jej  ostatni  argument  powinien
       być listą; elementy tej listy są traktowane tak, jakby były dodatkowymi
       argumentami funcall.

       Pierwszy argument mapcar  musi  być  funkcją  jednoargumentową;  mapcar
       stosuje  tą  funkcję  do każdego elementu listy i zbiera wyniki w innej
       liście.

       Funcall i apply są używane często gdy  ich  pierwszym  argumentem  jest
       zmienna.   Na przykład mechanizm przeszukiwania może brać jako parametr
       funkcję heurystyczną i używać funcall lub  apply  do  wołania  jej  dla
       opisu  stanu.   Funkcje  sortowania,  opisane  dalej używają funcall do
       wołania funkcji porównawczych.

       Mapcar wraz funkcjami bez  nazwy  (patrz  niżej)  może  zastąpić  wiele
       pętli.

Lambda

       Jeśli  chcesz  utworzyć  funkcję  tymczasową  i  nie chcesz nadawać jej
       nazwy, to możesz użyć lambda.

       > #'(lambda (x) (+ x 3))
       (LAMBDA (X) (+ X 3))
       > (funcall * 5)
       8
       Połączenie lambda i mapcar może  zastąpić  wiele  pętli.  Na  przykład,
       następujące postacie są równoważne:

       > (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 porównawcza.
       Funkcja sortująca nie gwarantuje stabilności:  jeśli  są  dwa  elementy
       takie,  że (and (not (< a b)) (not (< b a))) , to sort może zaaranżować
       je w dowolnym porządku. Funkcja stable-sort jest taka  sama  jak  sort,
       lecz  gwarantuje,  że  dwa  równoważne  elementy  pojawią  się w liście
       posortowanej w tej samej kolejności co na liście wejściowej.

       Uwaga: sort może niszczyć swój argument, więc jeśli sekwencja wejściowa
       jest  dla  ciebie ważna, utwórz jej kopię poleceniem copy lub copy-list
       czy copy-seq.

Równość

       LISP ma wiele różnych wizji równości. Równość numeryczna jest oznaczana
       przez  =.  Dwa  symbole  są  eq tylko gdy są identyczne. Dwie kopie tej
       samej listy nie są eq, choć są równe.

       > (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 równoważny eq dla symboli i = dla liczb.

       Equal jest równoważny eql dla symboli i liczb. Jest prawdziwy dla dwóch
       wagoników  tylko  gdy  ich car-y i cdr-y są sobie równe. Jest prawdziwy
       dla dwóch struktur tylko gdy wszystkie ich pola są sobie równe.

Przydatne funkcje listowe

       Oto funkcje, działające na listach.

       > (append '(1 2 3) '(4 5 6))    ;łącz (konkatenuj) listy
       (1 2 3 4 5 6)
       > (reverse '(1 2 3))            ;odwróć elementy listy
       (3 2 1)
       > (member 'a '(b d a c))        ;ustaw członkowstwo--zwraca pierwszy ogon
       (A C)                           ;w którym car jest żądanym elemetem.
       > (find 'a '(b d a c))          ;inny sposób ustawiania członkowstwa
       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ę zbiorów
       NIL
       > (intersection '(a b c) '(b))  ;przekrój zbiorów
       (B)
       > (union '(a) '(b))             ;suma zbiorów
       (A B)
       > (set-difference '(a b) '(a))  ;różnica zbiorów
       (B)

       Subsetp, intersection, union i set-difference  zakładają,  że  żaden  z
       argumentów  nie  posiada zduplikowanych elementów. Np.  (subsetp '(a a)
       '(a b b)) może się nie powieść.

       Find, subsetp, intersection, union i set-difference mogą brać  argument
       o słowie kluczowym :test; domyślnie wszystkie używają eql.

Początki z Emacsem

       Do  edycji  kodu  LISP  możesz  używać  Emacsa:  większość Emacsów jest
       skonfigurowania na wchodzenie w tryb LISP za każdym  razem  gdy  znajdą
       plik,  kończący  się na .lisp. Jeśli u ciebie tak się nie dzieje, wpisz
       M-x lisp-mode.

       Pod Emacsem możesz też uruchamiać LISP: upewnij się, że masz w  ścieżce
       komendę  o  nazwie  lisp, która uruchamia twojego ulubionego LISP-a. Na
       przykład możesz wpisać

               ln -s /usr/local/bin/clisp ~/bin/lisp

       Potem, w Emacsie wpisz M-x run-lisp. Możesz wtedy wysłać  kod  LISP  do
       interpretera  i  zrobić  wiele  innych  fajnych  rzeczy;  dla  dalszych
       informacji wpisz C-h m z dowolnego bufora w trybie LISP.

       W rzeczywistości nawet nie musisz tworzyć dowiązania. Emacs ma  zmienną
       o nazwie inferior-lisp-program; więc jeśli dodasz linię

               (setq inferior-lisp-program "/usr/local/bin/clisp")

       do  swojego pliku .emacs, to Emacs będzie wiedział gdzie szukać CLISP-a
       dla komendy M-x run-lisp.

AUTORZY

       Geoffrey  J.  Gordon  <ggordon@cs.cmu.edu>  (piątek,  5  lutego  1993).
       Poprawione   przez   Brunona   Haible'a   <haible@ma2s2.mathematik.uni-
       karlsruhe.de>.  Przetłumaczone na język polski  i  przekonwertowane  do
       postaci man przez Przemka Borysa <pborys@dione.ids.pl>

                                 wrzesień 1999                     LISP-TUT(5)