HOWTO - Lisp

Základní příkazy
http://service.felk.cvut.cz/courses/36JUI/Travnik/index.html
Debian GNU/Linux
apt-get install clisp
Komentář
; toto je komentář
Proměnné
(setf x 3)
(setf x '(1 2 3))
Funkce
(defun secti (x y)
	(+ x y)
)
Podmínky
T, cokoli - true
NIL, () - false

(defun vetsi (x y)
	(if (> x y)
		x
		y
)	)


(defun pridej (pr in se)
	(cond
		((null se) (list pr))
		((= in 0) (cons pr se))
		(T (cons (car se) (pridej pr (- in 1) (cdr se))))
)	)
Seznamy
> (list 1 2 3)
(1 2 3) - vytvoří seznam

> (car '(1 2 3))
1 - vrátí první prvek

> (cdr '(1 2 3))
(2 3) - vrátí seznam bez prvního prvku

> (last '(1 2 3))
(3) - vrátí poslední prvek

> (butlast '(1 2 3))
(1 2) - vrátí seznam bez posledního prvku

> (append '(1 2 3) '(4 5 6))
(1 2 3 4 5 6) - spojí seznamy do jednoho seznamu

> (cons 0 '(1 2 3))
(0 1 2 3) - přidá prvek na začátek seznamu

> (null '(1 2 3))
NIL
> (null '())
T - je seznam prázdný?
Funkce ctvrty (s), která vrátí čtvrtý prvek v seznamu
>
(defun ctvrty (s)
	(car (cdr (cdr (cdr s))))
)
CTVRTY
> (ctvrty '(1 2 3 4 5 6))
4
Funkce vs (x y), která vytvoří seznam (x x+1 x+2 ... x+y)
>
(defun vs (x y)
	(cond
		((zerop y) (list x))
		(T (cons x (vs (1+ x) (1- y))))
)	)
VS
> (vs 12 5)
(12 13 14 15 16 17)
Funkce otoc (x), která invertuje pořadí prvků v seznamu
>
(defun otoc (s)
	(if (null s)
		s
		(append (last s) (otoc (butlast s)))
)	)

> (otoc '(1 2 3 4 5))
(5 4 3 2 1)
Speciální volání funkcí
(function jmeno) - vrátí adresu funkce
#'jmeno - ekvivaletní zápis
(apply adresafunkce (seznam argumentů)) - zavolá funkci
(funcall adresafunkce argumenty) - zavolá funkci
(lambda (argumenty) (tělo)) - nepojmenovaná funkce

> (defun secti (a b) (+ a b))
SECTI
> (secti 1 2)
3

> (function test)
#<FUNCTION SECTI (A B) (DECLARE (SYSTEM::IN-DEFUN SECTI)) (BLOCK SECTI (+ A B))>
> #'secti
#<FUNCTION SECTI (A B) (DECLARE (SYSTEM::IN-DEFUN SECTI)) (BLOCK SECTI (+ A B))>

> (apply #'secti '(1 2))
3
> (funcall #'secti 1 2)
3
> (funcall #'(lambda (a b) (+ a b)) 1 2)
3
Mapovací funkcionály (obdoba foreach cyklů)
mapcar - operace nad prvky se stejným indexem, vrátí nový seznam o min. počtu prvků
mapcan - aplikuje fci na prvky se stejným indexem, výsledky jsou sloučeny do listu
mapc - výstup se neakumuluje, ale vrací se původní seznam
maplist
mapl
...

> (mapcar #'list '(1 2 3) '(7 9 12) '(4 6 5))
((1 7 4) (2 9 6) (3 12 5))

> (mapcar #'list '(1 2 3) '(7 9 12) '(4 6))
((1 7 4) (2 9 6))

> (mapcan (lambda (x) (list (+ x 10) 'x)) '(1 2 3 4))
(11 X 12 X 13 X 14 X)

> (mapcan (lambda (x) (if (> x 0) (list x) nil)) '(-4 6 -23 1 0 12 ))
(6 1 12)
Funkce prumery (a b), která zpracuje dva seznamy a vytvoří seznam průměrů
>
(defun prumery (a b)
	(mapcar #'(lambda (x y) (/ (+ x y) 2)) a b)
)

> (prumery '(1 3 5) '(3 5 7))
(2 4 6)
Proměnný počet parametrů funkcí
> (defun funkce (x y &rest z) (list x y z))
FUNKCE
> (funkce 1 2 3 4 5)
(1 2 (3 4 5))

> (defun funkce (x &optional y z) (list x y z))
FUNKCE
> (funkce 1 2)
(1 2 NIL)

> (defun funkce (x &optional (y 10) (z 20)) (list x y z))
FUNKCE
> (funkce 1 2)
(1 2 20)
Funkce maax, která vrátí největší hodnotu z parametrů
>
(defun maax (a &rest s)
	(cond
		((null (car s)) a)
		((< a (apply #'maax s)) (apply #'maax s))
		(T a)
)	)

> (maax 1 9 5 7 11 3)
11

> (defun maax (a &rest s)
	(setf tmp a)
	(mapc #'(lambda (z)
			(if (> z tmp)
				(setf tmp z)
			)
		)
	s)

	tmp
)

> (maax 1 9 5 7 11 3)
11
I/O
> (eval '(+ 1 2))
3

> (format t "~A mínus ~A je ~A ~%" 3 2 (- 3 2))
3 mínus 2 je 1
NIL

~A - tiskne příkazem princ
~S - tiskne příkazem prin1
~F - tiskne jako reálné číslo
~% - nový řádek

> (princ "ahoj")
ahoj
"ahoj"

> (prin1 "ahoj")
"ahoj"
"ahoj"

> (print "ahoj")

"ahoj"
"ahoj"


read - přečte token (tohle používá interpret
read-line - přečte řádku
read-char - přečte znak

> (read-line)
radka textu
"radka textu" ;
NIL

> (read-char)
a
#\a

> (read)
( 1   2 a b)
(1 2 A B)
Interpret lispu (fakt funguje)
(defun interpret ()
	(print "hlaska>")
	(print (eval (read)))
	(interpret)
)
Funkce, která čte vstup, dokud nedostane číslo a pak ho vytiskne
>
(defun chcicislo ()
	(format t "zadej: ")
	(setf nacteno (read))
	(if (numberp nacteno)
		(format t "~A ~%" nacteno)
		(chcicislo)
)	)

> (chcicislo)
zadej: a
zadej: a
zadej: b
zadej: 25
25
NIL
Funkce, která n-krát vytiskne písmeno X
>
(defun nkratx (n)
	(format t "X")
	(if (= n 1)
		()
		(nkratx (1- n))
	)
)

> (nkratx 5)
XXXXX
Funkce, která načte dva seznamy a spojí je
>
(defun spoj ()
	(format t "prvni: ")
	(setf prvni (read))
	(format t "druhy: ")
	(setf druhy (read))
	(append prvni druhy)
)

>(spoj)
prvni: (1 2 3)
druhy: (4 5 6)
(1 2 3 4 5 6)
Funkce, která do seznamu přidá prvek na specifikovanou pozici
>
(defun pridej (pr in se)
	(cond
		((null se) (list pr))
		((= in 0) (cons pr se))
		(T (cons (car se) (pridej pr (1- in) (cdr se))))
	)
)

> (pridej 'a 2 '(1 2 3 4 5))
(1 2 A 3 4 5)
Pole (indexy jsou od nuly)
; Pole, indexy jsou od nuly
> (setf x (make-array '(2 3)))
#2A((NIL NIL NIL) (NIL NIL NIL))
> (aref x 0 1)
NIL
> (setf (aref x 0 1) '(1 3))
(1 3)
> (aref x 0 1)
(1 3)
Struktura, záznam
> (defstruct zaznam
	(pol1 (progn (princ "Zadej cislo: ")(read)))
	(pol2 nil)
	pol3
)
ZAZNAM
> (setf x (make-zaznam))
Zadej cislo: 23
#S(ZAZNAM :POL1 23 :POL2 NIL :POL3 NIL)
> x
#S(ZAZNAM :POL1 23 :POL2 NIL :POL3 NIL)
> (zaznam-pol1 x)
23
> (setf (zaznam-pol1 x) 50)
50
> (zaznam-pol1 x)
50
Hashovací tabulka
> (setf ht (make-hash-table))
#S(HASH-TABLE :TEST FASTHASH-EQL)

> (gethash 'klic ht)
NIL ;
NIL
> (setf (gethash 'klic ht) 10)
10
> (gethash 'klic ht)
10 ;
T
> (setf (gethash 'klic2 ht) 2)
2

> (maphash #'(lambda (k h) (format t "Klic: ~A, hodnota: ~A ~%" k h)) ht)
Klic: KLIC2, hodnota: 2
Klic: KLIC, hodnota: 10
NIL
Funkce, která vytiskne četnosti prvků v seznamu
>
(defun cetnost (s)
	(setf ht (make-hash-table))
	(mapcar #'(lambda (x)
		(if (gethash x ht)
			(setf (gethash x ht) (1+ (gethash x ht)))
			(setf (gethash x ht) 1)
		)

	) s)

	(maphash #'(lambda (x y) (print (list x y))) ht)
)
CETNOST

> (cetnost '(a c b c d a a b))
(D 1)
(B 2)
(C 2)
(A 3)
NIL
Bloky
> (prog1 (+ 1 2) (+ 5 9) (+ 3 4))
3

> (prog2 (+ 1 2) (+ 5 9) (+ 3 4))
14

> (progn (+ 1 2) (+ 5 9) (+ 3 4))
7

>
(block prvni
	(+ 1 2)
	(+ 3 4)
	(block druhy
		(+ 5 6)
		(return-from prvni 10)
	)
)
10

>
(defun fn ()
	(format t "test")
	(return-from fn 10)
)
FN

> (fn)
test
10
Cykly
>
(dolist (i '(1 2 3) 'OK)
	(format t "~A ~%" (* i 2))
)
2
4
6
OK

>
(dotimes (i 3 'OK)
	(format t "~A ~%" (* i 2))
)
0
2
4
OK

>
(do
	(
		(i 1 (1+ i))
		(j 1 i)
		(k 1 j)
	)
	(
		(> i 5) 'OK
	)
	(format t "~A ~A ~A ~%" i j k)
)
1 1 1
2 1 1
3 2 1
4 3 2
5 4 3
OK

>
(do*
	(
		(i 1 (1+ i))
		(j 1 i)
		(k 1 j)
	)
	(
		(> i 5) 'OK
	)
	(format t "~A ~A ~A ~%" i j k)
)
1 1 1
2 2 2
3 3 3
4 4 4
5 5 5
OK
Funkce, která vrátí T, pokud jsou rozdíly dvou sousedních čísel v seznamu menší než daná hodnota
>
(defun rozdily (x s)
	(cond
		((and s (cdr s))
			(if (< (abs (- (first s) (second s))) x)
				(rozdily x (cdr s))
			)
		)
		(T)
	)
)
ROZDILY

> (rozdily 3 '(1 3 4 6 7))
T
> (rozdily 3 '(1 3 4 8 9))
NIL


>
(defun rozdily (x s)
	(setf j (car s))
	(dolist (i s)
		(if (> (abs (- j i)) x)
			(return-from rozdily nil)
		)
		(setf j i)
	)

	T
)
ROZDILY

> (rozdily 3 '(1 3 4 6 7))
T
> (rozdily 3 '(1 3 4 8 9))
NIL
Funkce, která vloží mezi každé dva prvky seznamu hvězdičku
>
(defun vloz (x s)
	(setf tmp ())

	(dolist (i s)
		(setf tmp (append tmp (list i)))
		(setf tmp (append tmp (list x)))
	)

	(butlast tmp)
)
VLOZ

> (vloz '* '(1 2 3 4))
(1 * 2 * 3 * 4)
Makra
- výsledkem makra je seznam příkazů, ten se vykoná a vrátí se hodnota
- za zpětný apostrof se píší příkazy s parametry makra
- ,x - se nahradí hodnotou předanou za x
- ,@x - pokud je x seznam, nahradí se svými prvky

> (setf tmp '(1 2 3 4))
(1 2 3 4)
> `(tmp - ,tmp - ,@tmp)
(TMP - (1 2 3 4) - 1 2 3 4)

>
(defmacro nastav3 (x)
	`(setf ,x 3)
)
NASTAV3

> (macroexpand-1 '(nastav3 y))
(SETF Y 3) ;
T

> (nastav3 y)
3
> y
3
Lokální proměnné
>
(let ((x 2) (y 3))
	(print x)
	(print y)
	(print (+ x y))
	'OK
)
2
3
5
OK

>
(let ((x (gensym)))
	; x obsahuje unikátní jméno pro pomocnou proměnnou v makru
)
Makro, které zajistí výpis expandovaného výrazu
>
(defmacro vypis (vyraz)
	`(pprint (macroexpand-1 ',vyraz))
)
VYPIS

> (vypis '(+ 1 2))
'(+ 1 2)
Makro, které provede nkrát své tělo
>
(defmacro nkrat (n &rest a)
	(let ((i (gensym)))
		`(dotimes (,i ,n) ,@a)
	)
)
NKRAT

> (nkrat 5 (princ "x"))
xxxxx
Makro cyklu for (řídícího proměnná, počáteční hodota, koncová hodnota, tělo)
>
(defmacro for ((x y z) &rest body)
	(let ((it (gensym)) (kroku (1+ (- z y))))
		`(dotimes (,it ,kroku) (setf ,x (+ ,y ,it)) ,@body)
	)
)
FOR

> (macroexpand-1 '(for (x 5 9) (princ x)))
(DOTIMES (#:G8115 5) (SETF X (+ 5 #:G8115)) (PRINC X)) ;
T

>(for (x 5 9) (princ x))
56789
NIL
Funkce, která ze dvou seznamů vytvoří seznam min. prvků na odpovídajících si pozicích
>
(defun mensi (a b)
	(mapcar
		#'(lambda (x y)
			(if (< x y)
				x
				y
			)
		)
		a b
	)
)
MENSI

> (mensi '(1 8 9 4) '(7 2 3 10))
(1 2 3 4)
Funkce, která určí průnik dvou množin
; Pozn.: Predpokládá, že vstupní seznamy jsou opravdu množiny
;       (tj. seznam obsahuje daný prvek vždy právě jednou)

>
(defun inters (a b)
	(setf ret ())

	(mapcar
		#'(lambda (x)
			(mapcar
				#'(lambda (y)
					(if (= x y)
						(setf ret (cons x ret))
					)
				)
				b
			)
		)
		a
	)

	ret
)
INTERS

> (inters '(1 2 3) '(2 3 4))
(3 2)
Funkce, která vypočítá dosažitelné uzly ze zadaného uzlu pro orientovaný graf zadaný seznamem uzlů a jejich sousedů
>
; Najde sousedy uzlu
(defun najdisousedy (uzel graf)
	(mapcar
		#'(lambda (i)
			(if (eq uzel (car i))
				(return-from najdisousedy i)
			)
		)
		graf
	)
)
NAJDISOUSEDY

>
; Počítá dosažitelné uzly v grafu (předpokládá, že je graf acyklický)
(defun dosazitelnost-acykl (uzel graf)
	(setf ret ())

	(mapcar
		#'(lambda (i)
			(setf ret (union ret (list i)))
			(setf ret (union ret (dosazitelnost-acykl i graf)))
		)

		(cdr (najdisousedy uzel graf))
	)

	ret
)
DOSAZITELNOST-ACYKL

; Acyklický orientovaný graf
; a -> b, c, d
; b -> c
; c -> d
; d
> (setf graf '((a b c d) (b c) (c d) (d)))
((A B C D) (B C) (C D) (D))

> (dosazitelnost-acykl 'a graf)
(B C D)
> (dosazitelnost-acykl 'b graf)
(C D)
> (dosazitelnost-acykl 'c graf)
(D)
> (dosazitelnost-acykl 'd graf)
NIL
Funkce, která vrací prvek z listu podle předaných operací
>
(defun best-of (S fn test)
	(setf tmp (car S))
	(mapc #'(lambda (z)
			(if (funcall test (funcall fn z) (funcall fn tmp))
				(setf tmp z)
			)
		)
	s)

	(list (funcall fn tmp) tmp)
)

> (best-of '(1 -2 -4 3) #'abs #'>)
(4 -4)
Copyright © 2001-2011 Michal Turek <WOQ (zavináč) seznam.cz>
Valid XHTML 1.0 Strict, Valid CSS