Zmienne w Lispie zapisujemy za pomocą funkcji setq.
(setq x 10)
=> 10
x
(setq y (* x 20))
=> 200
Wartość po znakach => określa wartość zwracaną przez intepreter Lispa.
Zmienne lokalne zapisujemy za pomocą konstrukcji let.
(let ((x 20))
(* x 30))
=> 600
(let ((zmienna1 wartość)
(zmienna2 wartość))
wyrażenie)
W powyższym kodzie zmienna x została przysłonięta przez konstrukcję let dlatego w jej wnętrzu zmienna x ma wartość 20 nie 10. Po wyjściu z konstrukcji let zmienna nie jest już widoczna.
Aby usunąć zmienną używamy funkcji (makunbound 'zmienna).
Kostrukcja let* działa tak jak let z tym że zmienne są przypisywane sekwencyjnie tzn. zmienne mogą się odwoływać do już przypisanych zmiennych, w przypadku let może się to odbywać równolegle.
(let* ((x 10)
(y (+ x 10)))
(* x y))
Aby przypisać stałą należy użyć funkcji defconstant. Przyjeło się, że stałe zapisuje się ze znakiem +.
(defconstant +pi+ 3.14159265358979)
Zmienne globalne przypisuje się za pomocą funkcji defvar lub defparameter. Przyjmuje sięże zmienne globalne zapisujemy ze znakami *.
(defvar *lista* '(1 2 3 4))
(defparameter *zmienna* 10)
Funkcja defvar w odróżnieniu od defparameter przypisuje zmiennej wartość tylko raz na samym początku.
Wszystkie zmienne są zmiennymi leksykalnymi, tzn. widocznymi tylko wewnątrz struktury, w której są definiowane, chyba że zapisano inaczej. Za pomocą funkcji special mamy możliwość zadeklarowania zmiennych jako dynamiczne.
(defun foo (x)
(declare (special x))
(bar))
(defun bar ()
(+ x 3))
W powyższym kodzie jeśli wywołamy funkcje (foo 3) zostanie zwrócona wartość 6, chociaż w funkcji bar nie zdefiniowano zmiennej x, zmienna przyjmie wartość 3.
Pętla dotimes.
(dotimes (zmienna_n opcjonalna-zwracana-wartość)
wyrażenie
...)
Pętla dotimes wywoła wyrażenie n razy. W każdej iteracji pętli zmienna przyjmie kolejną wartość (od zera do n-1). Opcjonalnie można w instrukcji dotimes określić wartość zwracaną przez pętle. Jeśli nie określimy tej wartość pętla zwróci wartość nil.
(dotimes (i 10)
(print i))
0
1
2
3
4
5
6
7
8
9
=> NIL
Powyższy kod wyświetli liczby od 0 do 9 i zwróci wartość nil.
Pętla dolist.
(dolist (e '(1 2 3 4 5 6) opcjonalna-zwracana-wartość)
Pętla dolist wywoła się tyle razy ile jest elementów listy. W każdej iteracji zmienna e przyjmie kolejną wartość z listy. Opcjonalnie można określić wartość zwracaną przez pętle. Jeśli nie określimy tej wartość to pętla zwróci wartość nil.
Pętla do.
(do ((zmienna1 wartość-początkowa step)
...
(zmienna2 wartość-początkowa step))
(warunek-zakończenia wartość-zwracana)
wyrażenia
Pętla do może iterować po kilku zmiennych. Dla każdej z nich określa się wartość początkową oraz wyrażenie step, które zostanie wywołane po każdej iteracji. Zakończenie pętli następuje wtedy, gdy zostanie spełniony warunek. Pętla zwróci określoną wartość.
(do ((i 0 (incf i))
(j 10 (decf j)))
((zerop j) 'done)
(print (+ i j)))
Powyższy kod iteruje po dwóch zmiennych, z których jedna jest zwiększana w każdej iteracji a druga zmniejszana. Pętla zostanie przerwana jeśli zmienna j osiągnie wartość zero. Zwrócona zostanie wtedy wartość 'done. W każdej iteracji pętli zostanie wyświetlona suma dwóch liczników "i" i "j" (zostanie wyświetlone 10 razy liczba 10). Makra incf i decf odpowiednio zwiększają i zmniejszą wartość swojego argumentu o 1.
Pętla loop w prostej postaci:
(loop
jest to pętla nieskończona.
(let ((i 10))
(when (zerop i) (return))
(print (decf i))))
Za pomocą makra return można przerwać pętlę.
Istnieje możliwość zastosowania rozszerzonej pętli loop. Poniżej przedstawiono jej możliwości.
Aby iterować po kolejnych liczbach od 1 do n:
for i from 1 to n ...)
(loop for x from 1 to 5
for y = (* x 2)
collect y)
Aby iterować po liczbach od 0 do n-1:
for i from 1 below n ...)
Aby iterować po liście wartości:
for element in (list 1 2 3 4 5 6) do wyrażenie ...)
(loop for x in '(a b c d e)
do (print x) )
for y in '(1 2 3 4 5)
collect (list x y) )
Wyrażenie do określa co ma zostać wywołane w każdej iteracji.
Aby iterować po tablicy, wektorze lub ciągu znaków :
for c across string collect c)
for c across “ala” collect c)
collect c tworzy listę z kolejnych wartości c.
Aby iterować po kilku listach używamy wyrażenie and:
for i in list1 and j in list2 collect (list i j))
for i in ‘(1 2 3) and j in ‘(a b c) collect (list i j))
Aby iterować po tablicy asocjacyjnej używamy notacji kropka:
for (k . v) in (pairlis '(a b c) '(1 2 3)) do
(format t "~a => ~a~%" k v))
C => 3
B => 2
A => 1
Fukcje format zostanie omówiona w innym dokumencie.
Aby iterować po parach cons używamy wyrażenia on:
for para on (list 1 2 3 4 5 6) do
(format t "~a => ~a~%" (car para) (cadr para)))
1 => 2
2 => 3
3 => 4
4 => 5
5 => 6
6 => NIL
Funkcja cadr zwraca drugi element listy.
Aby iterować po kluczach tablicy haszującej można użyć:
for k being the hash-keys of tablica-haszująca collect k)
Aby iterować po wartościach tablicy haszującej należy użyć poniższego kodu:
for v being the hash-values of tablica-haszująca collect v)
Poniższy kod wyświetla wszystkie klucze i wartości tablicy haszującej.
for k being the hash-keys of tablica-haszująca do
(format t "~a => ~a~%" k (gethash k tablica-haszująca)))
Tworzenie listy jeśli warunek jest spełniony:
for i in (list 0 1 2 3 4 5 6)
when (evenp i) collect i)
=> (0 2 4 6)
Powyższy kod utworzy listę wszystkich liczb parzystych (funkcja evenp).
Wykonywanie operacji jeśli warunek jest spełniony.
for i from 0 while (< i 10) collect i)
=> (0 1 2 3 4 5 6 7 8 9)
W powyższym kodzie za pomocą collect tworzymy listę od 0 do 9.
Podstawowym typem danych w Lispie są listy, listy składają się z par. Aby utworzyć parę używamy konstrukcji cons. Pierwszy element pary jest to bieżący element listy, natomiast drugim elementem...
stec007