Listy_petle.docx

(38 KB) Pobierz

Zmienne, pętle, listy

 

 

Zmienne

Zmienne w Lispie zapisujemy za pomocą funkcji setq.

 

(setq x 10)

=> 10

x

=> 10

(setq y (* x 20))

=> 200

   

Wartość po znakach => określa wartość zwracaną przez intepreter Lispa.

Zmienne lokalne

Zmienne lokalne zapisujemy za pomocą konstrukcji let.

 

(setq x 10)

(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))

   

 

 

Stałe

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 (dynamiczne)

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.

 

 

 

 

 

 

Petle

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ść)

  wyrażenie

  ...)

   

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

  wyrażenie

  ...)

   

jest to pętla nieskończona.

 

(let ((i 10))

  (loop

   (when (zerop i) (return))

   (print (decf i))))

9

8

7

6

5

4

3

2

1

0

=> NIL

   

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:

 

(loop

  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:

 

(loop

  for i from 1 below n ...)

   

Aby iterować po liście wartości:

 

(loop

  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) )

   

(loop for x in '(a b c d e)

      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 :

 

(loop

  for c across string collect c)

   

(loop

  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:

 

(loop

  for i in list1 and j in list2 collect (list i j))

 

(loop

  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:

 

(loop

  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:

 

(loop

  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ć:

 

(loop

  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:

 

(loop

  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.

 

(loop

  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:

 

(loop

  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.

 

(loop

  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.

Listy

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...

Zgłoś jeśli naruszono regulamin