Lisplogo_alien_256

Vorlesung 2 – Variablen, Scoping, Listen

Diese Woche haben wir uns mit Variablen und Listen beschäftigt. Insbesondere haben wir lexical vs dynamic, sowie local vs. global scoping studiert. Hier unten eine kurze Zusammenfassung, Sie finden mehr Materialien auf dem Ilias Server (Slides, sowie Code Beispiele). Im Zshg. mit diesem Thema finden Sie am Ende der Seit noch ein interessantes Video zum Lambda Calculus, bzw. dem Unterschied zwischen zustands-basierten (state-based) und funktionalen (functional) Sprachen.

 

Variablen

Lokale Variablen

  • let => erzeugt lokale, lexikalische  Variablen. Beispiel:

(let ((x 5) (y 10))
           (+ x y)
)

=> 15 ;  x und y können innerhalb des let-statements benutzt werden

Globale Variablen:

  • defvar => erzeugt Variable und weist einen Wert zu, allerdings nur wenn die Variable noch nicht definiert wurde. Beispiel:

(defvar *mydefvar* 'something)

  • defparameter => erzeugt Variable und weist ihr einen Wert zu. Beispiel:

(defparameter *mydefparameter* 'anotherthing)

  • defconstant => erzeugt eine Konstante. Beispiel:

(defconstant +pi+ 3.14)

; => globale Variablen sind (wie der Name schon sagt) global existent und überall benutzbar. PS Bitte beachten Sie die “earmuffs” Notation für globale *Variable*, bzw. +Konstanten+.

(* +pi+ 2)

=> 6.28

Setz-Operatoren

Die Werte von existenten lexikalischen und dynamischen Variablen lassen sich mit Setz-Operatoren (set, setq, setf) setzen*.

(let ((something 2.3))
(setq something 1)
(print  something)
)

; => “1”

(setq *mydefparameter* 5.0)
(print *mydefparameter*)

; => “5”

*Konstanten können nicht mit Setz-Operatoren verändert oder mit neuen Werten gebunden werden. Beispiel:

(setf  +pi+ 1.0) ; => ERROR

Lexikalisch (statisch)  vs  Dynamisch (special) 

  • Lexikalisch: Der Wert der Variablen wird durch den umgebenden Text (also “räumlich”) der Funktionsdefinition bestimmt. Beispiel:

(let ((x 5))
          (defun return-x () x)
)

(let ((x 10))
         (return-x)
)

=> 5 ;   der Wert von x aus der Umgebung der Funktionsdefinition

  • Dynamisch: Der Wert der Variablen wird zur Funktionslaufzeit (also zeitlich) bestimmt. Beispiel:

(defparameter *x* 5)

(defun return-x () *x*)

(setf *x* 10)

(return-x)

=> 10 ; der Wert von *x* zur Laufzeit der Funktion

Closures

Als Closure wird ein Konstrukt (Umgebung und Funktionsdefinition) bezeichnet, welches Funktionen Zugriff auf (lexikalische) Variablen erlaubt, die ausserhalb der Funktionsdefinition selbst, jedoch innerhalb des lexikalischen Scopes in der die Funktionen definiert wurden, gebunden sind. Beispiel:

(let ((number 10))
           (defun add1 () (incf number))
           (defun sub1 () (decf number))
       )

(add1) , => 11, 12, 13, ...

(sub1), => 9, 8, 7, ...

; Obwohl die Variable ‘number’ nicht innerhalb der Funktionen add1 und sub1 definiert wurde, kann Sie dennoch verwendet (und verändert) werden.

Für mehr Lektüre zu Variablen und Scoping empfehle ich Ihnen dringend diesen sehr guten Text:

http://www.gigamonkeys.com/book/variables.html

Hier aus Wikipedia:

Lexical scope vs. dynamic scope

A fundamental distinction in scoping is what “part of a program” means. In languages with lexical scope (also called static scope), name resolution depends on the location in the source code and the lexical context, which is defined by where the named variable or function is defined. In contrast, in languages with dynamic scope the name resolution depends upon the program state when the name is encountered which is determined by the execution context or calling context. In practice, with lexical scope a variable’s definition is resolved by searching its containing block or function, then if that fails searching the outer containing block, and so on, whereas with dynamic scope the calling function is searched, then the function which called that calling function, and so on, progressing up the call stack.[4] Of course, in both rules, we first look for a local definition of a variable.

Most modern languages use lexical scoping for variables and functions, though dynamic scoping is used in some languages, notably some dialects of Lisp, some “scripting” languages like Perl, and some template languages.[c] Even in lexically scoped languages, scope for closures can be confusing to the uninitiated, as these depend on the lexical context where the closure is defined, not where it is called.

Lexical resolution can be determined at compile time, and is also known as early binding, while dynamic resolution can in general only be determined at run time, and thus is known as late binding.

LISTEN

Wie haben uns Funktionen angeschaut, um Listen zu konstruieren, Informationen über Listen und ihre Elemente zu bekommen, sowie destruktive und nicht-destruktive Listen Operationen. Hier einige Beispiele:

(setf *mylist* (list 1 2 3 4)) => der Operator list konstruiert eine Liste.

; NB Die leere Liste () ist äquivalent zu NIL

(eq () nil) => T

car und cdr

(car *mylist*) ; äquivalent (first *mylist*)

=>  ; gibt erstes Element der Liste zurück

(cdr *mylist*) ; äquivalent (rest *mylist*)

=> (2 3 4) ; gibt den Rest oder “Tail” der Liste zurück

Informationen

(length *mylist*)

=> 4 ; gibt die Anzahl der Elemente (Länge) der Liste zurück

(count 2 *mylist*)

=> 1 ; gibt die Häufigkeit eines Elements in einer Liste zurück, also ist die Zahl 2 in der Liste ein mal vorhanden.

Nicht-Destruktive Operationen

(reverse *mylist*)

=> (4 3 2 1) ; gibt eine Kopie der Liste mit den Elementen in umgekehrter Reihenfolge (= Krebs) zurück

(nthcdr 2 *mylist*)

=> (3 4) ; wendet n mal cdr an = gibt den Rest der Liste ab einer bestimmten Stelle zurück

Destruktive Operationen

(pop *mylist*)

=> 1 ; gibt den car der Liste zurück und überschreibt die Liste mit dem cdr, d.h. ‘schneidet’ das erste Element destruktiv ab:

*mylist* => (2 3 4)

(push 1 *mylist*=> (1 2 3 4)

; “schiebt” ein Element destruktiv in eine Liste (die Stelle kann spezifiziert werden (z.B. (last *mylist*) ) und ist der Rückgabewert der Funktion.

Die Beschreibung der Funktionen ist als Einblick gedacht, bitte schlagen Sie für genauere Definitionen in der HyperSpec nach.