Zmienne lokalne i globalne
Na pierwszych zajęciach poznaliśmy operator setq( lub analogiczny setf). LISP daje nam jednak szereg innych sposobów na deklarowanie zmiennych, zarówno wywoływanych lokalnie jak i globalnie.
LET
Zmienne lokalne
Znane z innych języków programowania zmienne lokalne występują również w języku Common Lisp i ich użycie można zdecydowanie polecić wszędzie tam, gdzie nie jest konieczne przechowywanie danych dostępnych przez cały czas dla różnych funkcji. Do definiowania zmiennych lokalnych i określania ich zakresu służy operator specjalny LET. Ogólna postać zapisanej za jego pomocą formy jest następująca:
(let ((zmienna forma) (zmienna forma) ... (zmienna forma)) forma forma ... forma) |
---|
W pierwszej części formy LET występują lista zmiennych wraz z formami określającymi ich wartości początkowe, a w drugiej części lista dowolnych form, wartościowanych w kolejności, w jakiej zostały zapisane, w których mogą występować te zmienne. Mogą być tam one w szczególności także zmieniane za pomocą formy SETQ — jej użycie nie powoduje wówczas powołania zmiennej globalnej, lecz tylko nadaje nową wartość zmiennej lokalnej. Wartością formy LET jest wartość ostatniej formy z jej drugiej części. Po zakończeniu jej wartościowania definiowane w niej zmienne lokalne przestają istnieć. Oto proste przykłady użycia formy LET:
Przykład 2
> (let ((a 3)
(b 4)
(c 5))
(* (+ a b) c))
35
>a
Error: Unbound variable
> (setq a 89)
89
>a
89
> (let ((a 3))
(+ a 2))
5
>a
89
Zmienne globalne
Zmienne tworzone za pomocą formy setq są globalne, czyli istnieją i można się do nich odwoływać z dowolnego miejsca programu od chwili wykonania tej formy. Takie zmienne można również jawnie zadeklarować za pomocą makrodefinicji defvar:
> (defvar *x1*)
*x1*
> (defvar *x2* 10)
*x2*
Zwyczaj nakazuje, aby pierwszym i ostatnim znakiem nazwy takiej globalnej zmiennej był znak *, co ułatwia ich identyfikację w tekście programu. Podanie początkowej wartości definiowanej zmiennej jest opcjonalne. Do zmiany wartości można następnie używać w zwykły sposób formy setq. Wielokrotne wykonanie formy defvar dla tej samej zmiennej ma skutek równoważny jej pierwszemu wykonaniu. Oznacza to w szczególności, że powtórne wykonanie tej formy z inną wartością początkową nie zmienia wartości zmiennej, co widać w poniższym przykładzie.
> (defvar *z* 10)
*Z*
> *z*
10
> (defvar *z* 20)
*Z*
> *z*
10
Inaczej zachowuje się makrodefinicja defparameter, która pod innymi względami jest równoważna makrodefinicji defvar: tutaj efekt jej wielokrotnego wykonania dla tej samej zmiennej jest taki sam, jak efekt ostatniego wykonania, co w szczególności daje możliwość zmiany wartości. Poprzedni przykład przybiera dla formy defparamater następującą postać:
> (defparameter *z* 10)
*Z*
> *z*
10
> (defparameter *z* 20)
*Z*
> *z*
20
Na definiowanie jeszcze innego rodzaju zmiennych globalnych pozwala makrodefinicja defconstant. Zdefiniowana za jej pomocą zmienna jest ustalona, co oznacza, że jej początkowej wartości nie można zmieniać. Zwyczajowo nazwy zmiennych ustalonych wyróżnia się rozpoczynając i kończąc je znakiem +, tak jaj w poniższym przykładzie.
> (defconstant +g+ 9.81)
+G+
Wartości nadawane zmiennym za pomocą operatorów setq, defvar, defparameter i defconstant nie muszą być stałymi, jak w podanych przykładach — mogą to być dowolne poprawne formy, które są obliczane w zwykły sposób w celu określenia wartości zmiennej.
Listy
Listy tworzymy przy użyciu operatora list lub zapisując elementy listy w obiekcie np. użycie operatora ( list 1 6 8 10) da nam ten sam wynik co ‘( 1 6 8 10) .
Stworzone listy możemy przyporządkować do zmiennych lokalnych lub globalnych przy użyciu poznanych operatorów setq, setf.
( setq lista_probna ‘ ( 99 88 77))
Operatory first, rest, second, third…tenth.
reverse
(reverse nazwa_listy)
Odwracanie kolejności elementów
length
(length nazwa_listy)
Zwraca liczbę elementow w sekwencji.
count
(count 3 '(2 3 4 5 2 3))
Funkcja zwraca liczbę elementow występujących w sekwencji, w tym przypadku 2.
remove
(remove element nazwa_listy)
Funkcja usuwa wszystkie wystąpienia danego elementu z sekwencji.
substitute
(substitute zastąpiony zastępowany sekwencja)
Funkcja zastępuje każdy element zastąpiony zastępowanym.
find
(find element sekwencja)
Funkcja zwraca znaleziony element w sekwencji lub wartość nil.
append
(append lista1 lista2)
Złącza dwie podane listy
union
(union ‘(9 7) (‘ 9 10 19))
( 9 7 10 19)
Traktuje listy jako zbiory i zwraca ich sumę
Intersection
(intersection ‘(9 7) ‘( 9 10 19))
(9)
Operacja przecięcia( części wspólnej) dwóch list.
Zadania
Stwórz listy lista1 ( 10 15 123) oraz lista2 ( 17 34 85) a następnie lista3, która będzie złączeniem lista1 i lista2.
Sprawdź czy 2 element lista3 jest większy od 10. Jeżeli jest większy zwróć wartość T, jeżeli nie NIL.
Przyporządkuj nowej liście lista4 wartość Lista1 + Lista2 – część wspólna (Lista1 Lista2)
Dodaj do lista4 listę ‘( 100 88 134).
Zapisz warunek, który zwróci wartość T, jeżeli długość lista1, lista2 i lista 3 jest większa od 3, w przeciwnym wypadku NIL.
Stwórz funkcję, która zsumuje długości wszystkich stworzonych do tej pory list, czyli innymi słowy poda ile jest elementów w lista1, lista2, lista3 i lista4.
Napisz funkcję sumująca elementy dowolnej listy.(PODPOWIEDŹ: w warunku skorzystaj z predykatu null, który zwraca wartość prawda jeżeli obiekt jest pusty np. (null lista1)
nil
Napisz funkcję wypisującą trzeci element listy.