Definícia funkcie
(defun name (parameter*) [ documentation-string ] body-form*)
Okrem obyčajného zoznamu argumentov je možné použiť nepovinné pomenované "keyword" argumenty:
CL-USER> (defun fn (&key one (two 2) (three 3 three-p)) (list one two three-p three)) FN CL-USER> (fn :one 0 :two 1 :three 2) (0 1 T 2)
Z výstupu je možné vyčítať, že sme nastavili všetkým nové hodnoty,
pri poslednom môžeme priamo vo funkcii zistiť či bol zadaný
(three-p
má hodnotu T
, pravdivý výraz).
Ďalej máme k dispozícii nepovinné argumenty:
CL-USER> (defun fn (&optional one (two 2)) (list one two)) FN CL-USER> (fn 0 1) (0 1) CL-USER> (fn 0) (0 2) CL-USER> (fn) (NIL 2)
A v neposlednom rade neurčitý počet argumentov:
CL-USER> (defun fn (one two &rest rest) (list one two rest)) FN CL-USER> (fn 1 2 3) (1 2 (3)) CL-USER> (fn 1 2 3 4) (1 2 (3 4))
Za zoznamom argumentov ešte môže nasledovať nepovinný dokumentačný reťazec:
(defun hello () "Tento retazec sa stava sucastou funkcie." (format t "Hello world!~%"))
CL-USER> (documentation 'hello 'function) "Tento retazec sa stava sucastou funkcie."
Už minule sme použili funkciu format
, kde sme tiež
vypisovali na štandardný výstup (aby sa reťazec nevypisoval ale použil
ako návratová hodnota, prvý argument musí byť nil
).
Táto funkcia dokáže formátovať rôznymi spôsobmi, jej formátovací
reťazec je taký malý špecializovaný jazyk a rozsah dokumentácie je
väčší než celý tento diel.
~~ | znak tilda, ~n~ je n tíld |
~% | nový riadok, ~n% je n nových riadkov |
~F / ~E / ~G | desatinné číslo |
~nR | vypíše číslo so základom n (D/B/O/X miesto nR pre desiatkovú/binárnu/osmičkovú/šestnástkovú sústavu) |
~C | ďalší argument v poradí je znak |
~A | pekný ("aesthetic") výpis akéhokoľvek argumentu |
~{ a ~} | iterácia nad zoznamom |
CL-USER> (format nil "~{~B ~}~%" '(1 2 3 4)) "1 10 11 100 " CL-USER> (format t "~{~A:~7T~3B~%~}" '(:one 1 :two 2 :three 3 :four 4)) ONE: 1 TWO: 10 THREE: 11 FOUR: 100 NIL CL-USER> (format nil "~R" 1234) "one thousand two hundred thirty-four" CL-USER> (format nil "~@R" 1234) "MCCXXXIV"
Toto je len zlomok celkových možností formátovania, aj keď tie najexotickejšie sme už vyčerpali.
Zoznam
Zoznam je zatiaľ všade okolo nás, je to totiž veľmi šikovný dátový
typ, vhodný na použitie ako zásobník (funkcie push
,
pop
), pole a pod. (Pozor, Common Lisp má aj polia, hashe a iné
typy, zoznam nie je zďaleka jediný.)
Základné funkcie na prácu so zoznamom:
first
/car
,
second
/cadr
,
third
/caddr
, …,
rest
/cdr
, last
,
nth
, intersection
(prienik),
union
(zjednotenie), append
a iné.
Zoznam sa vnútorne skladá z nadväzujúcich dvojíc ("dotted
pair"), ktoré dokáže skladať funkcia cons
:
CL-USER> (cons 1 nil) (1) CL-USER> (cons nil 1) (NIL . 1) CL-USER> (cons 1 '(2 3)) (1 2 3) CL-USER> (last (cons 1 (cons 2 (cons 3 4)))) (3 . 4) CL-USER> (cons 1 (cons 2 (cons 3 (cons 4 nil)))) (1 2 3 4) CL-USER> (last (cons 1 (cons 2 (cons 3 (cons 4 nil))))) (4) CL-USER> (nth 0 (cons 1 (cons 2 (cons 3 (cons 4 nil))))) 1 CL-USER> (nth 3 (cons 1 (cons 2 (cons 3 (cons 4 nil))))) 4
Zoznam tvoria zreťazené dvojice, prvá je hodnota a druhá odkaz na
nasledujúcu dvojicu (a prvok poslednej dvojice musí byť
nil
). Toto zreťazenie je vlastne spájaný zoznam.
Špeciálnym zoznamom je tzv. "property list", ktorý obsahuje pomenované prvky:
CL-USER> (defvar prop '(1 2 :three 3 4)) PROP CL-USER> (getf prop :three) 3 CL-USER> (setf (getf prop :three) 4) 4 CL-USER> prop (1 2 :THREE 4 4)
Čísla
Už sme videli celé čísla aj desatinné čísla, oboje v matematike patria pod reálne. Taktiež zlomky:
CL-USER> 1/3 1/3 CL-USER> (/ 1 3) 1/3
Toto spolu s neobmedzenou veľkosťou dáva výbornú presnosť (na druhú
stranu to stojí procesorový čas, preto používame aj čísla typu
float
). Common Lisp poskytuje aj komplexné čísla:
CL-USER> #C(2 2) #C(2 2) CL-USER> (+ #C(2 2) #C(2 2)) #C(4 4) CL-USER> (* #C(2 2) #C(2 2)) #C(0 8) CL-USER> (abs #C(2 2)) 2.828427 CL-USER> (sqrt -1) #C(0.0 1.0)
Ďalšie samozrejmé funkcie sú bitové operácie a narábanie s bitovou
reprezentáciou: bit
, ash
,
bit-not
, bit-and
, bit-xor
,
byte
, ldb
, dpb
, …
Na záver si predstavíme rôzne operátory rovnosti (či skôr predikáty), ktoré máme k dispozícii:
= | porovnáva len čísla |
eq | porovnáva objekty, zisťuje či sa jedná o totožný objekt (je pravdivý napr. po priradení pomocou setq ) |
eql | porovnáva typ a hodnotu |
equal | zistí či objekty "vyzerá" rovnako (pre čísla, znaky a reťazce sa správa ako eql ) a nedokáže porovnať polia (okrem reťazcov) |
equalp | ignoruje typy čísel ako =, reťazce a znaky sú porovnávané case-insensitive |
Pozornejší si už mohli všimnúť -P konvenciu (dostala sa aj do Jargon file). Je to pridávanie písmena 'p' na koniec názvu predikátu (s pomlčkou alebo bez, dávame najmä ak predchádza viac slov – v Lispe sa slová zvyknú oddeľovať pomlčkami). Common Lisp obsahuje veľa predikátov a funkcií, kde sa dajú využiť ako argument (v prípade komplexnejších porovnaní je možné na mieste vytvoriť anonymnú funkciu).
Nabudúce sa pozrieme zase na nejaké teoretické témy, ale znovu si niečo naprogramujeme.
dodam, ze jednorozmerne pole ma v CL aj samostatny typ vector (okrem array). okrem toho ma aj ine datove typy, ktore su optimalizovane.