2.2.4. Bindungen und Variablen
Bindungen sind ein zweites wichtiges Konzept der Sprache Lisp. Unter Bindung versteht man die Verknüpfung eines Symbols (einer 'Variablen') mit einer Bedeutung. Es gibt 'lokale' und 'globale' Bindungen.
Lokale Bindung
Eine lokale (englisch 'lexical') Bindung hat nur innerhalb des Kontextes (der Klammerebene), in dem sie definiert wird, eine Bedeutung. Lokale Bindungen werden durch die special forms
let
undlet*
definiert.
;; lokale Bindung (let ((x 3)) x) ;; -> 3 ;; Global ist die Variable x nicht gebunden: x ;; -> The variable x is unbound
In einem let
Ausdruck können mehrere Variablen gleichzeitig ('parallel') gebunden werden. Im Unterschied hierzu findet die Bindung bei let*
'sequentiell' statt und ermöglicht so die Definition neuer Bindungen auf der Basis von davor definierten anderen Bindungen des selben let*
Ausdrucks.
;; Parallele Bindung mehrerer Symbole mit let: (let ((x 3) (y 5)) (list x y)) ;; -> (3 5) ;; Sequentielle Bindung des Symbols y mit let* unter Verwendung des ;; Symbols x aus demselben Ausdruck: (let* ((x 3) (y (+ x 4))) (list x y)) ;; -> (3 7) ;; Der vorherige Ausdruck erzeugt bei let einen Fehler: (let ((x 3) (y (+ x 4))) (list x y)) ;; -> The variable x is unbound.
Globale Bindungen
Globale Bindungen4 werden durch die Makros
defparameter
,defvar
unddefconstant
erzeugt. Mit Hilfe vonsetq
bzw.setf
kann Symbolen eine neue Bedeutung zugewiesen werden. Symbole, die mitdefconstant
definiert wurden, können nicht mirsetq
odersetf
neu gebunden werden.
;; globale Bindungen ;;; Parameter sind globale Bindungen. Es gibt die Konvention, ;;; Variablennamen globaler Bindungen mit dem Zeichen * einzurahmen, um ;;; zu kennzeichnen, dass es sich um globale Variablen handelt. (defparameter *test* 4) ;; -> *test* *test* ;; -> 4 (setf *test* 12) ;; -> 12 *test* ;; -> 12 (setq *test* 34) ;; -> 34 *test* ;; -> 34 ;;; Parameter können wiederholt neudefiniert werden (defparameter *test* 122) ;; -> *test* *test* ;; -> 122 (setf *test* 30) *test* ;; -> 30 ;; Variablen verhalten sich wie Parameter, können aber nur einmal ;; definiert werden: (defvar *testvar* 4) ;; -> *testvar* *testvar* ;; -> 4 (defvar *testvar* 12) ;; -> *testvar* *testvar* ;; -> 4 (setf *testvar* 12) ;; -> 12 *testvar* ;; -> 12 ;; Konstanten können nicht verändert werden: (defconstant +testconstant+ 3.1415927) +testconstant+ ;; -> 3.1415927 (setq +testconstant+ 21) ;; -> Error: ;; +testconstant+ is a constant and thus can't be set.
Evaluation/Quotierung
Wenn der Lisp Reader auf ein Symbol trifft, wird das Symbol immer evaluiert. Wie bei Listen kann die Evaluation durch ein vorangestelltes einfaches Anführungszeichen verhindert werden.
(defparameter *global2* 7) ;; -> *global2* *global2* ;; -> 7 ;; Quotierung verhindert Evaluation: '*global2* ;; -> *global2* ;; auf diese Weise können Symbole mit ihrem Namen in eine Liste ;; integriert werden, auch wenn sie gar nicht an einen Wert gebunden ;; sind: (list '*global2* *global2* 'a) ;; -> (*global2* 7 a) ;; Wenn die vorherige Liste nicht mit der Funktion #'list evaluiert ;; wird, sondern quotiert wird, werden die einzelnen Elemente nicht ;; ausgewertet: '('*global2* *global2* 'a) ;; -> ('*global2* *global2* 'a) ;; Bei Atomen als Listenelementen wäre das Ergebnis in beiden Fällen ;; gleich: (list 1 2 3 "hallo" 17.3) ;; -> (1 2 3 "hallo" 17.3) '(1 2 3 "hallo" 17.3) ;; -> (1 2 3 "hallo" 17.3)
Shadowing
Es ist möglich, eine globale Bindung lokal zu "überschreiben". In der Fachsprache nennt sich dies 'shadowing'. Dieses shadowing geschieht nur in dem lexikalischen Kontext der neuen Bindung. Ausserhalb dieses Kontextes bleibt die ursprüngliche Bedeutung der Variable erhalten.
(defparameter *global* 34) ;; -> *global* ;; Wert der globalen Variable *global* *global* ;; -> 34 ;; lokale Neubindung des Symbols *global* (let ((*global* 12)) *global*) ;; -> 12 ;; Der Wert der globalen Variable bleibt erhalten *global* ;; -> 34
4: In Lisp werden solche globalen Variablen 'special variables' genannt. ↩