Skip to content
 
 

Repository files navigation

#+title: LISP-Kurs
#+author: Sebastian Jordan
#+latex_header: \usepackage[ngerman]{babel}

* License
  Copyright (C) 2015 Sebastian Jordan.  Permission is granted to copy,
  distribute and/or modify this document under the terms of the GNU
  Free Documentation License, Version 1.3 or any later version
  published by the Free Software Foundation; with no Invariant
  Sections, no Front-Cover Texts, and no Back-Cover Texts.  A copy of
  the license is included in the section entitled "GNU Free
  Documentation License".

* Anleitung fuer dieses Dokument
  Dieses Dokument enthaelt sehr viel Schemecode.  Du kannst den Code
  extrahieren, sofern du GNU Make und Emacs auf deinem System
  installiert hast.  Fuehre einfach den Befehl
  #+begin_src sh
    make all
  #+end_src
  im Verzeichnis aus, in dem die Datei =README.org= liegt.  Eine
  pdf-Version dieses Dokuments wird ebenfalls erzeugt, sofern =latex=
  auf deinem System installiert ist.

* Einfuehrung
  Dieser Text soll dabei Helfen, einen konzeptuellen Zugang zum
  Schreiben von Computerprogrammen aus einer funktionalen Perspektive
  zu geben.

** Themen
   * Rekursion
   * Datenstrukturen
   * Streams & Lazy evaluation
   * Concurrency

** Material
   * [[https://www.gnu.org/software/emacs/][Emacs]] :: Programmiereditor mit gutem LISP/Scheme-Support
   * [[http://www.vim.org/][Vim]] :: Standard Linuxtexteditor der auf fast allen Systemen
            installiert ist (Vi)
   * [[https://mitpress.mit.edu/sicp/][Structure and Interpretation of Computer Programs]] :: Ein wirklich
        sehr gutes Lehrbuch zum Thema, das den Author stark
        beeinflusst hat.
   * [[https://www.gnu.org/software/guile/][Guile]] :: Wir benutzen Guile als Schemeinterpreter
   * [[http://orgmode.org/][org-mode]] :: Dieses Dokument ist mit Hilfe von org-mode verfasst.

* Ein Beispiel: Wurzel nach Newtonverfahren

  #+caption: =sqrt-newton.scm=
  #+begin_src scheme :tangle examples/sqrt-newton.scm
    (define (sqrt-newton x)
      ;; iteration step
      (define (sqrt-iter guess)
        (if (good-enough? guess)
            guess
            (sqrt-iter (improve guess))))

      ;; test if we are already good enough with our guess
      (define (good-enough? guess)
        (<= (abs (- (square guess) x)) 0.0001))

      ;; square a number
      (define (square n) (* n n))

      ;; improve a guess
      (define (improve guess)
        (avarage guess (/ x guess)))

      (define (avarage a b)
        (/ (+ a b) 2.0))

      ;; start the iteration with 1 as initial guess
      (sqrt-iter 1))

    ;; test the function
    (define test (sqrt-newton 4))
    (display "Die Wurzel von 4 ist ")
    (display test)
    test
  #+end_src

  #+RESULTS:
  : 2.0000000929222947

  Diese Beispiel findest du unter dem Namen =examples/sqrt-newton.scm=, wenn du
  die =.scm=-Dateien gemaess der obigen Anleitung erzeugt hast.

* Wiederholung: Funktionen & Blockstruktur
** Aufgabe 1.3
   Hier ist eine Beispielloesung fuer die Aufgabe 1.3 aus dem Buch:

   #+begin_src scheme
     (define (add-and-mult a b c)
       (define (second-greatest m n o)
         (if (and (<= m n) (<= m o))
             (min n o)
             (if (and (<= n m) (<= n o))
                 (min m o)
                 (min m n))))
       (define greatest max)
       (define (square x) (* x x))
       (+ (square (second-greatest a b c))
          (square (greatest a b c))))

     ;; test the function
     (add-and-mult 4 2 3)
   #+end_src

   #+RESULTS:
   : 25

   Das Ergebnis des Tests:
   #+RESULTS:
   : 25

** Aufgabe 1.8
   Zum Loesen der Aufgabe 1.8 verwenden wir die selbe Strategie wie
   fuer das Finden der Quadratwurzel.  Wir veraendern allerdings die
   =improve=-Funktion.

   #+begin_src scheme
     (define (cuberoot-newton x)
       (define (cubert-iter guess)
         (if (good-enough? guess)
             guess
             (cubert-iter (improve guess))))
       (define (good-enough? guess)
         (>= 0.001
             (abs (- (cube guess) x))))

       ;; new improve function
       (define (improve guess)
         (/ (+ (* 2. guess) (/ x (square guess)))
            3.))

       (define (cube n) (* n (square n)))
       (define (square n) (* n n))
       (cubert-iter 1))

     ;; test the function
     (cuberoot-newton 125.0)
   #+end_src

   #+RESULTS:
   : 5.000000000287929

* Rekursion
  Wir wollen die Fakultaet einer Zahl berechnen.  Dazu uebertragen wir
  die Definition der Fakultaet in Scheme.

  \begin{align}
    !x &= x \cdot !(x - 1) \\
    !0 &= 1
  \end{align}

  Eine intuitivie Definition der Fakultaet koennte folgende sein:
  #+begin_src scheme :exports both
    (define (factorial x)
      (if (<= x 1)
          1                           ;; base case
          (* x (factorial (- x 1))))) ;; recursive step

    ;; test the function
    (factorial 6)
  #+end_src

  #+RESULTS:
  : 720

  Dies ist eine vereinfachte Darstellung der Auswertung der obigen
  Funktion.  Wie wir sehen koennen, benoetigt die Funktion "linear
  viel" Speicher.
  #+begin_src scheme
    (factorial 5)
    (* 5 (factorial 4))
    (* 5 (* 4 (factorial 3)))
    (* 5 (* 4 (* 3 (factorial 2))))
    (* 5 (* 4 (* 3 (* 2 (factorial 1)))))
    (* 5 (* 4 (* 3 (* 2 1))))
    (* 5 (* 4 (* 3 2)))
    (* 5 (* 4 6))
    (* 5 24)
    120
  #+end_src

  Unser Ziel ist es, nur konstant viel Speicher -- also unabhaengig
  von der eingegebnene Zahl -- zu verbrauche.  Dazu wandeln wir die
  rekursive Definition der Fakultaet in einen iterativen Prozess um.
  #+begin_src scheme :exports both
    (define (factorial x)
      (define (iter accu count)
        (if (= count x)
            (* count accu)
            (iter (* accu count) (+ count 1))))
      (iter 1 1))

    (factorial 5)
  #+end_src

  #+RESULTS:
  : 120

  Fuer eine Iteration benoetigen wir (genauso wie in Python und Co)
  nur konstant viel Speicher.  Hier ist dargestellt wie der
  Interpreter den Funktionskoerper der obigen Funktion auswerten
  koennte.
  #+begin_src scheme
    (define x 3)
    (iter 1 1)
    (iter 1 2)
    (iter 2 3)
    6
  #+end_src

** Fibonacci
   Die ersten 10 Elemente der Fibonaccireihe.

   | fib(n) | 0 | 1 | 1 | 2 | 3 | 5 | 8 | 13 | 21 | 34 |
   |--------+---+---+---+---+---+---+---+----+----+----+
   | n      | 1 | 2 | 3 | 4 | 5 | 6 | 7 |  8 |  9 | 10 |

   Eine rekursive Definition der Reihe:
   \begin{equation}
     fib(n) = fib(n -1) + fib(n - 2)
   \end{equation}

   Hier ist eine Pseudoimplementation der Fibnoaccireihe im
   imperativen Stil:
   #+begin_src
     int a <- 0
     int b <- 1
     for i in (3..n)
       int c <- a + b
       a <- b
       b <- c
     return b
   #+end_src

   Als Uebungsvorschlag: Du koenntest versuchen, die Fibonaccireihe
   als Rekursion & Iteration zu implementieren (Siehe Fakultaet).

   Eine rekursive Beispielimplementation fuer die Fibonaccireihe:
   #+begin_src scheme :exports both
     (define (fib-rec n)
       (cond ((< n 1) (error "FIB-REC: index to small"))
             ((= n 1) 0)
             ((= n 2) 1)
             ((> n 2) (+ (fib-rec (- n 1)) (fib-rec (- n 2))))))
     (fib-rec 10)
   #+end_src

   #+results:
   : 34

   Hier ist eine iterative Beispielimplementation der Fibonaccizahlen.
   #+begin_src scheme :exports both
     (define (fib-iter n)
       (define (iter counter n-1 n-2)
         (if (= counter n)
             n-1
             (iter (1+ counter) (+ n-1 n-2) n-1)))

       (cond ((= n 1) 0)
             ((= n 2) 1)
             (else (iter 2 1 0))))
     (fib-iter 10)
   #+end_src

   #+results:
   : 34

* Listen
  Listen bestehen aus Paaren.

** Paare
   Paare sind zusammengesetzte Datenstrukturen, das heisst, dass sich
   Paare in kleinere Bestandteile zerlegen lassen und, vor allem, sich
   aus kleineren Bestandteilen zusammen bauen lassen.

   Paare sind "Behaelter", die genau 2 Werte speichern koennen.  Es
   gibt einen "ersten" Wert und einen "zweiten" Wert, die eindeutig
   Adressierbar sein muessen.

   Es folgt eine Beispielinterface fuer das Programmieren mit Paaren:
   #+begin_src scheme
     (define (pair a b)
       (error "PAIR: undefined"))
     (define (1st p)
       (error "1ST: undefined"))
     (define (2nd p)
       (error "2ND: undefined"))

     ;; What would you get?
     (1st (pair 1 2)) ;; 1
     (2nd (pair 1 2)) ;; 2

     (1nd (2nd (2nd (pair 1
                          (pair 2
                                (pair 3
                                      4))))))
     ;; 3
   #+end_src

*** Und in Scheme?
    In Scheme sind die =pair=-, =1st=- und =2nd=-Funktion schon definiert.

    * pair == cons
    * 1st == car
    * 2nd == cdr

    Beispiel fuer =car=:
    #+begin_src scheme :exports both
      (define new-pair (cons 1 2))
      (car new-pair)
    #+end_src

    #+results:
    : 1

    Beispiel fuer =cdr=:
    #+begin_src scheme
      (define new-pair (cons 1 2))
      (cdr new-pair)
    #+end_src

    #+results:
    : 2

    Andere nuetzliche Funktionen im Zusammenhang mit Paaren:
    #+begin_src scheme
      (pair? (cons 1 2)) ;; #t
      (pair? 1) ;; #f

      #nil ;; #nil ist der sogenannte Nullzeiger und signalisiert KEINEN
           ;; Wert.
      (null? #nil) ;; #t
      (null? 1) ;; #f
    #+end_src

** Definition der Primitiven
   Hier ist eine Definition von "Paaren" (ohne =pair?=).
   #+caption: =<<custom-definition-pairs>>=
   #+name: custom-definition-pairs
   #+begin_src scheme
     (define (my-cons a b)
       (define (dispatch mode)
         (cond ((= mode 1) a)
               ((= mode 2) b)
               (else (error "COND: Argument not [1..3] -- " mode))))
       dispatch)

     (define (my-car list)
       (list 1))

     (define (my-cdr list)
       (list 2))
   #+end_src

   Auswertung der Implementation per Befehlssubstitution:
   #+begin_src scheme
     ;; testevaluation (KOMMENTIEREN)
     (my-car (my-cons 5 8))
     ;; zuerst werten wir den Rueckgabewert von my-cons aus.  my-cons gibt
     ;; uns eine Funktion zurueck (dispatch), die hier durch das lambda
     ;; dargestellt wird.
     (my-car (lambda (mode) (cond ((= mode 1) 5)
                                  ((= mode 2) 8))))

     ;; Jetzt wird my-car ausgewertet.  my-car "bewirkt" dass das Argument
     ;; (also in diesem Fall die "lambda"-Funktion ein Argument bekommt und
     ;; dann ausgewertet wird.
     ((lambda (mode)
        (cond ((= mode 1) 5)
              ((= mode 2) 8)))
      1)

     ;; Nun wird der Aufruf der "lambda"-Funktion durch den Koerper der
     ;; Funktion ersetzt.
     ((define mode 1)
      (cond ((= mode 1) 5)
            ((= mode 2) 8)))
     5
   #+end_src

** Jetzt wirklich Listen
   Listen sind in Scheme einfach nur "geschachtelte" Paare.
   #+caption: =<<definitions-lists>>=
   #+name: definitions-lists
   #+begin_src scheme :tangle examples/definitions-lists.scm
     ;; definitions-lists
     ;;;;;;;;;;;;;;;;;;;;

     (define empty-list #nil)

     (define (list-empty? list) (null? list))

     ;; put an element in front of the list
     (define (prepend elem list)
       (cons elem list))

     ;; put an element in the end of a list
     (define (append list elem)
       (if (null? list)
           (cons elem #nil)
           (cons (car list) (append (cdr list) elem))))

     ;; get the first element of a list
     (define (head list)
       (cond ((pair? list) (car list))
             ((null? list) (error "HEAD: list is empty"))
             (else (error "HEAD: object is not a list"))))

     ;; get all but the first element of a list
     (define (tail list)
       (cond ((pair? list) (cdr list))
             ((null? list) (error "TAIL: list is empty"))
             (else (error "TAIL: object is not a list"))))

     ;; get all but the last element of a list
     (define (init list)
       (cond ((null? list) (error "INIT: empty list given"))
             ((null? (cdr list)) #nil)
             (else (cons (car list)
                         (init (cdr list))))))

     ;; get the last element of a list
     (define (last list)
       (cond ((null? list) (error "LAST: empty list given"))
             ((null? (cdr list)) (car list))
             (else (last (cdr list)))))

     ;; get the n-th element of a list (starting with 0)
     (define (index list n)
       (if (= n 0)
           (car list)
           (index (cdr list) (1- n))))
   #+end_src

** Generalisierung
   Wenn wir mit Listen zu tun haben, dann kommen bestimmte "Probleme"
   oft vor.  Betrachten wir zum Beispiel das folgende Stueckchen Code:

   #+caption: =examples/map-01.scm=
   #+begin_src scheme :tangle examples/map-01.scm :noweb no-export
     <<definitions-lists>>

     ;; This procedure adds 1 to every element
     (define (add-one list)
       (if (list-empty? list)
           empty-list
           (prepend (1+ (head list))
                    (add-one (tail list)))))

     (define numbers '(1 2 3 4))
     (display "The original list is ")
     (write numbers)
     (newline)
     (display "add-one applied to the list results in ")
     (write (add-one numbers))
     (newline)

     ;; This procedure multiplies every element by 2
     (define (mult-two list)
       (if (list-empty? list)
           empty-list
           (prepend (* 2 (head list))
                    (mult-two (tail list)))))

     (define numbers '(1 2 3 4))
     (display "The original list is ")
     (write numbers)
     (newline)
     (display "mult-two applied to the list results in ")
     (write (mult-two numbers))
     (newline)
   #+end_src

   Beide Funktionen machen etwas sehr Aehnliches.  Es wird ueber eine
   Liste iteriert.  Dabei wird auf jedes Element eine Operation
   angewendet und so eine neue Liste erzeugt.

   #+begin_example scheme
     (define (<function> list)
       (if (list-empty? list)
           empty-list
           (prepend (<operation> (head list))
                    (<function> (tail list)))))
   #+end_example

   Die Generalisierung dieser beiden Funktionen wird =map= genannt.
   Wir koennen diese Idee allgemein in Scheme formulieren:

   #+caption: =<<definition-map>>=
   #+name: definition-map
   #+begin_src scheme :noweb no-export
     (define (map operation list)
       (if (list-empty? list)
           empty-list
           (prepend (operation (head list))
                    (map operation (tail list)))))
   #+end_src

   Im folgenden Stueckchen Code benutzen wir =map= um weitere
   Funktionen zu definieren.

   #+caption: =examples/map-02.scm=
   #+begin_src scheme :noweb no-export :tangle examples/map-02.scm
     <<definitions-lists>>
     <<definition-map>>

     (define (add-one list)
       (map 1+ list))

     (define (mult-two list)
       (map (lambda (x)
              (* 2 x))
            list))

     (write (mult-two '(1 2 3 4 5)))
     (newline)
     (write (add-one '(1 2 3 4 5)))
     (newline)
   #+end_src

** Hausaufgabe
   Wir stellen uns einmal vor, dass wir eine Liste von Zahlen gegeben
   haben und wollen alle Zahlen aufsummieren.  Der Code dafuer wurde
   wohl in etwa folgendermasse aussehen:

   #+caption: =examples/sum.scm=
   #+begin_src scheme :tangle examples/sum.scm :noweb no-export
     ;; We have to include the definitions for our list primitives
     <<definitions-lists>>

     (define (sum-list list)
       (define (iter accu current)
         (if (list-empty? current)
             accu
             (iter (+ accu (head current)) (tail current))))
       (iter 0 list))

     (define numbers '(1 2 3 4 5 6))
     (display "The sum of ")
     (write numbers)
     (display " is ")
     (write (sum-list numbers))
     (newline)
   #+end_src

   Wie koennen wir diese Funktion generalisieren?  Wenn du im Internet
   recherchieren willst, dann suche nach den Stichworten =fold=, =left
   fold=, =foldl=, wie zum Beispiel [[https://duckduckgo.com/?q%3Dscheme%2Bfold&t%3Dffab][hier]] (der Link funktioniert aus
   irgendeineem Grund nicht auf der github-Seite) geschehen.

*** Loesung
    Die =sum-list= Funktion macht prinzipiell 2 Dinge:
    1. Die Funktion iteriert ueber die List (so wie in =map=).
    2. Die Funktion akkumuliert Werte, die in der Liste gespeichert
       sind mittels einer Kombinationsfunktion.

    #+caption: =<<definition-foldl>>=
    #+name: definition-foldl
    #+begin_src scheme
      (define (foldl accu-fun start list)
        (cond ((list-empty? list) start)
              (else (foldl accu-fun
                           (accu-fun start (head list))
                           (tail list)))))

    #+end_src

    Wir koennen nun die =foldl=-Funktion fuer verschiedene Dinge nutzen:
    #+caption: =examples/foldl.scm=
    #+begin_src scheme :tangle examples/foldl.scm :noweb no-export
      ;; We have to include list primitives
      <<definitions-lists>>
      ;; ... and foldl
      <<definition-foldl>>
      <<definition-map>>

      ;; The sum function
      (define (sum list) (foldl + 0 list))

      ;; The length function
      (define (length list)
        (foldl (lambda (accu e)
                 (1+ accu))
               0
               list))

      ;; We can even define a filter function
      (define (filter predicate list)
        (foldl (lambda (accu-list current)
                 (if (predicate current)
                     (append accu-list current)
                     accu-list))
               empty-list
               list))
    #+end_src

    #+caption: =<<definition-filter>>=
    #+name: definition-filter
    #+begin_src scheme
      (define (filter pred list)
        (foldr (lambda (x accu)
                 (if (pred x)
                     (prepend x accu)
                     accu))
               empty-list
               list))
    #+end_src

** foldr
   Manchmal wollen wir aber auch ueber eine Liste von "hinten" aus
   iterieren.  Aehnlich wie =foldl= wollen wir eine
   Accumulationsfunktion und einen Startwert angeben koennen.  Die
   Funktion soll dabei jedes Element nur einmal ansehen.

   #+caption: =<<definition-foldr>>=
   #+name: definition-foldr
   #+begin_src scheme
     (define (foldr f start list)
       (cond ((null? list) start)
             (else (f (car list)
                      (foldr f start (cdr list))))))
   #+end_src

** Hausaufgaben
   * =mkList= :: Hat 1 Argument, n.  Soll Liste der Laenge n erzeugen,
                 mit nur 1en drin.
                 #+begin_src scheme
                   (define (mkList n)
                     (cond ((= n 0) #nil)
                           (else (cons 1 (mkList (- n 1))))))

                 #+end_src
   * =mkNumbers= :: Hat 1 Argument, n.  Soll Liste erzeugen, mit den
                    Zahlen 1 bis n.
                    #+begin_src scheme
                      (define (mkNumbers n)
                        (define (iter current)
                          (cond ((= current n) #nill)
                                ((< current n)
                                 (cons (+ 1 current) (iter (+ 1 current))))
                                (else (error "Internal error"))))
                        (iter 0))

                      (define (mkNumbers2 n)
                        (define (iter current acc)
                          (cond ((= current n) acc)
                                ((< current n) (iter (+ 1 current) (append acc (+ 1 current))))))
                        (iter 0 #nil))

                      (define (mkNumber3 n)
                        (if (= n 0)
                            #nil
                            (append (mkNumber3 (- n 1)) n)))


                    #+end_src
   * =iter-list= :: Hat 3 Argumente
     * iter-fun :: Ist eine Funktion, die ein Argument hat
     * start-val :: Hat den passenden Typen zu iter-fun
     * n :: Integer, so viele Elemente soll die Liste am Ende haben
     #+caption: =<<definition-iter-list.scm>>=
     #+name: definition-iter-list.scm
     #+begin_src scheme
       (define (iter-list fun start len)
         (define (iter current current-elem)
           (cond ((= current len) #nil)
                 ((< current len)
                  (cons current-elem (iter (+ 1 current) (fun current-elem))))
                 (else (error "Internal error"))))
         (iter 0 start))
     #+end_src

   #+begin_src scheme
     (iter-list 1+ 0 10)
     ;; '(0 1 2 3 4 5 6 7 8 9)

     (iter-list (lambda (x) (cons 1 x)) empty-list 3)
     ;; '(#nil '(1) '(1 1))
   #+end_src

** The List dropth, the List taketh
   Manchmal sind wir an den ersten n Elementen einer Liste
   interessiert.  Wir koennen dann entsprechend oft =head= und =tail=
   anwenden.

   #+begin_src scheme
     (define (first-3-elems xs)
       (list (head xs) (head (tail xs)) (head (tail (tail xs)))))
   #+end_src

   Die Funktion =first-3-elems= nimmt eine Liste entgegen und gibt
   eine neue Liste zurueck, die die ersten 3 Elemente enthaelt.  Wir
   koennen diese Funktion zu einer allgemeineren Funktion
   abstrahieren, die eine Liste und eine Zahl n entgegen nimmt und die
   ersten n Elemente der Liste zurueck gibt.

   #+caption: =<<definition-take>>=
   #+name: definition-take
   #+begin_src scheme
     (define (take n xs)
       (cond ((= n 0) empty-list)
             ((list-empty? xs)
              (error "-- TAKE: tried to get an element from the empty list"))
             (else (cons (head xs) (take (1- n) (tail xs))))))
   #+end_src

   Analog dazu koennen wir auch eine Funktion definieren, die die
   ersten n Elemente einer Liste verwirft und den "Rest" zurueck gibt.

   #+caption: =<<definition-drop>>=
   #+name: definition-drop
   #+begin_src scheme
     (define (drop n xs)
       (cond ((= 0 n) xs)
             ((list-empty? xs)
              (error "-- DROP: cannot drop another element from the empty list"))
             (else (drop (1- n) (tail xs)))))
   #+end_src

** Was noch fehlt... Sortieren!
   Wir haben gelernt, wie wir

   * Listen (mit Hilfe von "higher order functions" erzeugen koenne
   * primitive Operationen auf Listen durchfuehren koennen, die
     einzelne Elemente der Liste manipulieren
   * wiederkehrende Operationen abstrahieren koennen und "higher order
     functions" nutzen koennen um weniger ( = besseren) Code zu
     schreiben.

   Wir haben noch nicht gelernt, wie wir Listen sortieren.  Hier ist
   eine Beispielimplementation von Quicksort.  Sie sortiert eine Liste
   von Zahlen aufsteigend der Groesse nach.

   #+caption: =examples/quicksort.scm=
   #+begin_src scheme :tangle examples/quicksort.scm :noweb no-export
     <<definitions-lists>>
     <<definition-map>>
     <<definition-foldl>>
     <<definition-foldr>>
     <<definition-filter>>

     (define (concat l1 l2)
       (foldr (lambda (x accu)
                (prepend x accu))
              l2
              l1))

     (define (concat3 l1 l2 l3)
       (concat l1
               (concat l2 l3)))

     (define (quicksort numbers)
       (define (qs)
         (let* ((pivot (head numbers))
                (lower (filter (lambda (x) (< x pivot))
                               (tail numbers)))
                (bigger (filter (lambda (x) (>= x pivot))
                                (tail numbers))))
           (begin
             (write lower)
             (display " ")
             (write pivot)
             (display " ")
             (write bigger)
             (newline)
             (concat3 (quicksort lower)
                      (list pivot)
                      (quicksort bigger)))))

       (cond ((list-empty? numbers) empty-list)
             (else (qs))))
   #+end_src

   Leider ist die Verwendung dieser Funktion darauf beschraenkt,
   Zahlen der Groesse nach zu sortieren. Wir koennen diese
   Beispielimplementation abstrahieren, indem wir "offen" lassen,
   welche Vergleichsoperation beim Vergleich verwendet werden soll.
   Auf diese Art koennen wir alle Listen nach beliebigen Kriterien
   sortieren.

   #+name: =<<definition-sort>>=
   #+name: definition-sort
   #+begin_src scheme
     (define (quicksort smaller-than xs)
       (if (list-empty? xs)
           empty-list
           (let*
               ((pivot (head xs))
                (non-pivot (tail xs))
                (< (lambda (x) (smaller-than x pivot)))
                (>= (lambda (x) (not (smaller-than x pivot))))
                (smaller (filter < non-pivot))
                (bigger (filter >= non-pivot)))
             (concat3 (quicksort smaller-than smaller)
                      (list pivot)
                      (quicksort smaller-than bigger)))))

     ;; Hier ist noch eine Implementation von mergesort
     (define (mergesort smaller-or-equal-than xs)
       (define (merge as bs)
         (cond ((list-empty? as) bs)
               ((list-empty? bs) as)
               (else (let
                         ((a (head as))
                          (b (head bs)))
                       (if (smaller-or-equal-than a b)
                           (prepend a
                                    (merge (tail as) bs))
                           (prepend b
                                    (merge as (tail bs))))))))
       (let*
           ((len (length xs))
            (first-half (take (quotient len 2) xs))
            (second-half (drop (quotient len 2) xs)))
         (if (<= (length xs) 1)
             xs
             (merge (mergesort smaller-or-equal-than
                               first-half)
                    (mergesort smaller-or-equal-than
                               second-half)))))
   #+end_src

   Der Vollstaendigkeit halber, hier noch einmal die Definition von
   =concat3= sauber notiert.

   #+name: definition-concat
   #+begin_src scheme
     (define (concat l1 l2)
       "Concatenate l1 with l2"
       ;; We choose foldr to prepend all the elements of l1 to l2.  If we
       ;; chose to fold from the left and append every element of l2 to l1,
       ;; we would had a runtime behavior of O(n*m + n^2/2) where
       ;;
       ;; * n = length of l1
       ;; * m = length of l2
       ;;
       ;; This way we have O(n) as runtime behavior. (Why?)
       (foldr (lambda (current accu)
                (prepend current accu))
              l2
              l1))

     (define (concat3 l1 l2 l3)
       "Concatenate 3 lists l1 l2 l3"
       ;; First we concatenate l3 and l2, which in turn gets concatenated
       ;; with l1, which gives us a runtime behavior of $ O(n + m) $ where
       ;;
       ;; * n = length of l1
       ;; * m = length of l2
       ;; ( What would be the runtime behavior of
       ;;   (concat (concat l1 l2) l3)
       ;;   ?)
       (concat l1
               (concat l2
                       l3)))
   #+end_src

** Zusammenfassung, eine kleine Library
   Bis hier her haben wir uns angesehen, was wir alles mit Listen
   anstellen koennen.  Wir haben gelernt wie wir Listen als Paare
   darstellen koennen und haben sogar Paare als Funktionen
   dargestellt.  Wir haben mathematische Probleme effizient geloest
   (Fibonacci, Fakultaet) und daraus wiederkehrende Prozesse zu
   Funktionen abstrahiert.  Die Funktionen, die wir dabei definiert
   haben, koennen wir zu einer Library zusammenfassen.  Wir nennen sie
   =lists.scm=.

   #+caption: =<<lists.scm>>= (=lib/lists.scm=)
   #+name: lists.scm
   #+begin_src scheme :tangle lib/lists.scm :noweb no-export
     <<definitions-lists>>
     <<definition-map>>
     <<definition-foldl>>
     <<definition-foldr>>
     <<definition-filter>>
     <<definition-iter-list>>
     <<definition-take>>
     <<definition-drop>>
     ;; We have to define concat3 before the sorting algorithms because we
     ;; use these in their definition.
     <<definition-concat>>
     <<definition-sort>>
   #+end_src

* Binaere Suchbaeume
  Baeume sind genauso wie Listen in erster Linie eine Abstraktion
  ueber Daten.  Listen abstrahieren Daten als eine Sequence die von
  vorne nach hinten durchgeblaettert werden kann.  Das soll uns
  ermoeglichen, ueber Daten als eine Einheit nachdenken zu koennen.

  Listen sind fuer viele Dinge gut, vor allem wenn es um iterative
  Prozesse geht.  Fuer manche Dinge eignen sich Listen allerdings
  nicht so gut, wie zum Beispiel das Finden von Daten, welches nur mit
  einer Zeitkomplexitaet von $O(n)$ realisiert werden kann, selbst
  wenn die Liste bereits sortiert ist.  Listen sind auch nicht so
  toll, wenn es um das hinzufuegen neuer Daten geht.  Das hinzufuegen
  eines Elements zum Beginn einer Liste geht schnell, aber alles
  andere dauert viel laenger.  Zur Erinnerung: Die =append=-Funktion
  muss bis ans Ende der Liste iterieren, wenn es Element angehaengt
  werden soll.

** Struktur
   Baeume sind, so wie Listen, rekursive Datenstrukturen.  Fuer Listen
   beduetet dass, dass jede Liste entweder leer ist, oder die
   Verkettung eines Elements mit einer List.  Baeume sind sehr
   aehnlich definiert: Jeder Baum ist entweder leer oder ein Element
   verkettet mit zwei Unterbaeumen.  Die Unterbaeume heissen "linker
   Unterbaum" und "rechter Unterbaum".

   #+caption: =<<tree-constructors>>=
   #+name: tree-constructors
   #+begin_src scheme
     ;; Definitions of tree constructors
     ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

     ;; a leaf is just an empty list
     (define leaf empty-list)
     (define leaf? null?)

     ;; a branch is a value and two subtrees
     (define (branch val left right)
       (list val left right))
     (define branch-value car)
     (define branch-left cadr)
     (define branch-right caddr)
   #+end_src

   Die Baeume, die wir hier betrachten wollen heissen "binaere
   Suchbaeume", binaer, weil jeder Branch ("Zweig") zwei Unterbaeume
   hat und Suchbaum, weil wir die Baeume, die wir benutzen geordnet
   sein sollen, also zum Suchen und Finden von Werten (Daten)
   verwendet werden.  Die Ordnung auf unserem Baum koennen wir
   folgendermassen beschreiben: Fuer jeden Zweig in unserem Baum gilt,
   dass alle Elemente, die im linken Unterbaum existieren kleiner als
   das im Zweig gespeicherte Element sind und alle Elemente im rechten
   Unterbaum sind grosser als das im Zweig gespeicherte Element.  Dies
   ermoeglicht uns, ad hoc einen Algorithmus zu beschreiben, der
   beliebige vergleichbare(!!!) Elemente in unserem Baum zu finden.

   #+begin_src scheme
     <<tree-constructors>>

     (define (lookup-integer tree n)
       (cond ((leaf? tree) #f)
             ((= n (branch-value tree)) #t)
             ((< n (branch-value tree))
              (lookup-integer (branch-left tree) n))
             (else
              (lookup-integer (branch-right tree) n))))
   #+end_src

   Es ist leicht zusehen, dass der gegebene Algorithmus rekursiv
   definiert ist.  Wenn wir wissen wollen, ob eine Zahl in einem Leaf
   ("Blatt") zu finden ist, dann antwortet der Algorithmus mit =#f=,
   da ein Leaf keine Werte enthaelt.  Sollte die Funktionen einen
   Branch finden, dann ueberpruefen wir zu erst, ob das gesuchte
   Element im aktuellen Branch gespeichert ist, sollte das der Fall
   sein, geben wir =#t= zurueck.  Sollte auch das nicht der Fall sein,
   wird ueberprueft, ob die gesuchte Zahl kleiner oder groesser ist,
   als das aktuelle Element (=branch-value=).  Wenn das gesuchte
   Element nun also kleiner ist, wissen wir, dass es auf Grund der
   oben definierten Ordnung nur im linken Unterbaum stecken kann.  Im
   "groesser"-Fall kann es wiederum nur im rechten Unterbaum stecken
   und wir setzen unsere Suche dort fort.

   Es stellt sich nun die Frage, wie wir einen Baum konstruieren
   koennen, und es stellt sich heraus, dass die Konstruktion fast
   genauso wie die Suche ablaeuft.  Wenn wir eine Element $x$ zu einem
   leeren Baum, also Leaf, hinzufuegen wollen, dass geben wir einen
   Branch zurueck, dessen =branch-value= gerade $x$ ist und dessen
   Unterbaeume leere sind.  Sollten wir versuchen das Element zu einem
   Branch hinzuzufuegen, dann tritt einer der folgenden drei Faelle
   ein:

   - x = =branch-value= :: Das Element ist bereits im Baum enthalten
        und wir geben einfach den Baum selbst zurueck.
   - x < =branch-value= :: Um die Ordnung des Baumes zu bewahren,
        wissen wir, dass $x$ dem linken Unterbaum hinzugefuegt werden
        muss.
   - x < =branch-value= :: Aequivalent zum obigen Fall muessen wir $x$
        dem rechten Unterbaum hinzufuegen, um die Ordung zu wahren.

   #+begin_src scheme
     (define (insert-int tree x)
       (cond ((leaf? tree) (branch x leaf leaf))
             ((= x (branch-value tree)) tree)
             ((< x (branch-value tree))
              (branch (branch-value tree)
                      (insert-int (branch-left tree) x)
                      (branch-right tree)))
             (else
              (branch (branch-value tree)
                      (branch-left tree)
                      (insert-int (branch-right tree) x)))))
   #+end_src

   Damit haben wir die atomaren Operationen auf unserem Baum
   definiert.  Die Funktionen die wir definiert haben sind aber auf
   =integer=-Werte spezialisiert, wir wuerden aber gern Baeume mit
   beliebigen vergleichbaren Elementen betrachten koennen.  Dafuer
   brauchen wir eine Moeglichkeit Vergleiche zu kodieren.  Wir waehlen
   dazu folgende Form:

   Ein Vergleich ist eine Funktion mit zwei Parametern.

   1. Wenn diese Funktion $1$ zurueck gibt, ist das erste Argument
      groesser als das zweite Argument.
   2. Wenn die Funktion $0$ zurueck gibt, sind beide Argumente
      gleichwertig.
   3. Wenn die Funktion $-1$ zurueck gibt, ist das erste Argument
      groesser als zweite.

   Die folgende Funktion "implementiert" eine Vergleichsfunktion fuer

   #+begin_src scheme
     (define (comp-int x y)
       (cond ((< x y) -1)
             ((> x y) 1)
             (else 0)))
   #+end_src

   Mit einer solchen Funktion koennen wir eine =insert=-Funktion
   definieren, unabhaengig von konkreten Vergleichsoperationen
   funktioniert.

   #+caption: =<<tree-insert>>=
   #+name: tree-insert
   #+begin_src scheme
     (define (insert comp elem tree)
       (cond ((leaf? tree) (branch elem leaf leaf))
             (else
              (let* ((left (branch-left tree))
                     (right (branch-right tree))
                     (val (branch-value tree))
                     (comp-val (comp elem val)))
                (cond ((= comp-val 1)
                       (branch val left (insert comp elem right)))
                      ((= comp-val -1)
                       (branch val (insert comp elem left) right))
                      ((= comp-val 0)
                       (branch elem left right))
                      (else (error "insert: supplied comparison funktion is illdefined"
                                   comp)))))))
   #+end_src

   Die =lookup=-Funktion ist aequivalent.

   #+caption: =<<tree-lookup>>=
   #+name: tree-lookup
   #+begin_src scheme
     (define (lookup comp elem tree)
       (cond ((leaf? tree) #f)
             (else
              (let* ((val (branch-value tree))
                     (left (branch-left tree))
                     (right (branch-right tree))
                     (comp-val (comp elem val)))
                (cond ((= comp-val 0) val)
                      ((= comp-val 1)
                       (lookup comp elem left))
                      ((= comp-val -1)
                       (lookup comp elem right))
                      (else
                       (error "lookup: supplied comp function is ill defined "
                              comp)))))))
   #+end_src

   Wir koennen nun Werte einem Baum hinzufuegen und ueberpruefen, ob
   ein Wert im Baum gespeichert ist.  Manchmal wollen wir aber auch
   einen Wert aus dem Baum loeschen.  Loeschen soll an dieser Stelle
   konstruktiv verstanden werden.  Wir wollen bestehende Baeume nicht
   modifizieren (in der Tat wissen wir noch gar nicht wie wir
   IRGENDEINEN Wert modifizieren koennen), sondern einen neuen Baum
   erschaffen, in dem alle Werte aus dem alten Baum vorhanden sind,
   bis auf den zu loeschenden Wert.  Das Loeschen von Werten aus
   Baeumen ist ein wenig komplizierter als das Loeschen von Werten aus
   Listen (=filter=), da wir darauf achten muessen, dass die Struktur
   des Baumes erhalten bleibt.  Die Strategie beim Loeschen ist
   folgendermassen:

   Wenn wir Wert $x$ aus Baum $t$ loeschen wollen, suchen wir zu erst
   die Stelle an der $x$ im Baum steht.  Falls $x \not\in t$ geben wir
   einfach den urspruenglichen Baum zurueck.  Falls $x \in t$,
   unterscheiden wir drei Faelle:

   - $x$ hat kein Kind :: In diesem Fall ersetzen wir den Branch auf
        dem $x$ gespeichert ist mit einem Leaf.
   - $x$ hat ein Kind :: In diesem Fall ersetzen wir $x$ durch sein
        Kind.
   - $x$ hat zwei Kinder :: Wir tauschen $x$ mit dem "linkesten" Wert
        im rechten Unterbaum von $x$, und fuehren diesen Fall damit
        auf Fall 1 oder 2 zurueck.

   #+caption: =<<tree-delete>>=
   #+name: tree-delete
   #+begin_src scheme
     (define (delete comp elem tree)
       ;; delete the leftest node of a tree and return a pair of the
       ;; deletet value and the new tree
       (define (delete-leftest t)
         (let ((left (branch-left t))
               (right (branch-right t))
               (val (branch-value t)))
           (cond ((leaf? left)
                  (cons val
                        right))
                 (else
                  (let ((pair (delete-leftest left)))
                    (cons (car pair)
                          (branch val (cdr pair) right)))))))
       (cond ((null? tree) leaf) ;; The value is not in the tree
             (else
              (let* ((left (branch-left tree))
                     (val (branch-value tree))
                     (right (branch-right tree))
                     (comp-val (comp elem val)))
                (cond ((= 1 comp-val)
                       (branch val left (delete comp elem right)))
                      ((= -1 comp-val)
                       (branch val (delete comp elem left) right))
                      ((and (leaf? left) (leaf? right)) leaf)
                      ((leaf? right) left)
                      ((leaf? left) right)
                      (else
                       (let ((l (delete-leftest right)))
                         (branch (car l) left (cdr l)))))))))
   #+end_src

* Module
  Guile/Scheme stellt ein Modulesystem bereit, auf das wir von nun an
  zurueck greifen wollen.  Module werden mit dem Befehl =use-modules=
  geladen.  Weitere Infos dazu findet ihr im [[https://www.gnu.org/software/guile/manual/html_node/Using-Modules.html#Using-Modules][Handbuch]] von Guile. Um
  z.B. die =fold=-Implementation fuer Listen zu benutzen, laden wir
  das Modul =(srfi srfi-1)=.

  #+begin_src scheme :exports both
    (use-modules (srfi srfi-1))

    (define (sum ls)
      (fold + 0 ls))

    (sum '(1 2 3 4 5))
  #+end_src

  Eine [[https://www.gnu.org/software/guile/manual/html_node/Guile-Modules.html#Guile-Modules][Liste der verfuegbaren Standardmodule]] findet ihr auch im
  Handbuch.

* Pattern matching
  Es kann immer mal wieder vorkommen, dass wir Funktionen
  schreiben/benutzen, deren Rueckgabewerte oder Argumente
  umterschiedliche Strukturen haben koennen.  Das einfachste Beispiel
  an dieser Stelle ist =map= fuer Listen.

  #+begin_src scheme
    (define (map fun l)
      (cond ((null? l) l)
            (else
             (cons (fun (car l))
                   (map fun (cdr l))))))
  #+end_src

  Wir unterscheiden, ob das Argument =l= gerade =#nil= ist oder ein
  Paar.  Dieses Muster kommt in funktionaler Programmierung relativ
  haeufig vor.  Scheme bietet eine andere Moeglichkeit dieses Problem
  anzugehen: Pattern matching.

  #+begin_src scheme
    (use-modules (ice-9 match))

    (define (map fun l)
      (match l
        (()
         '())
        ((head tail ...)
         (cons (fun head)
               (map fun tail)))))
  #+end_src

  Diese Implementation von =map= "ueberprueft" die Struktur von =l=.
  Handelt es sich um die leere Liste, wird diese leere Liste zurueck
  gegeben.  An sonsten wird die Liste aufgeteilt in =head= und =tail=,
  wobei die Elemente der Liste an die entsprechenden Namen gebunden
  werden, =fun= wird auf =head= angewendet und das Ergebnis dann mit
  dem "gemapten" =tail= "geconst".

  Weitere Infos zum Thema "pattern matching" findest du im [[https://www.gnu.org/software/guile/manual/html_node/Pattern-Matching.html#Pattern-Matching][Handbuch
  von Guile]].

* Streams
  Streams sind (so, wie Listen auch) Abstaktionen ueber Daten.  Wir
  stellen uns Streams als (un-)endlich lange Sammlung von Daten vor,
  die wir nacheinander abrufen koennen.  Ein Stream muss folgenden
  Gesetzmaessigkeiten gehorchen:

  * =(car-stream (cons-stream a b))= = =a=
  * =(cdr-stream (const-stream a b))= = =b=

  Das sieht ja erstmal genauso wie die Definition einer Liste aus.  Es
  gibt aber einen kleinen Unterschied zwischen Listen uns Streams:
  Streams berechnen ihr die enthaltenen Werte nur auf Abruf.

  #+caption: =examples/strict-map.scm=
  #+begin_src scheme :tangle examples/strict-map.scm :noweb no-export
    <<definitions-lists>>
    <<definition-map>>

    (define (print-and-mult-2 x)
      (display x)
      (newline)
      (* 2 x))

    (head (map print-and-mult-2 (list 1 2 3 4)))
  #+end_src

* Functor
  Ein Functor ist eine Abstraktion ueber Daten.  Ein Functor
  ermoeglicht das Transformieren von Daten innerhalb einer
  Datenstruktur.  Diese Transformationsfunktion wird haeufig =map=
  oder =fmap= genannt.

  Diese =fmap=-Funktion muss ein paar Regeln gehorchen, um in die
  Kategorie Functor zu fallen.

  1. =(fmap id x) = x=
  2. =(fmap g (fmap f x)) = (fmap (compose g f) x)=

  Die erste Functorregel sagt aus, dass wenn ich =fmap= mit der
  Indentitaet auf einen Wert anwende, dann soll der Wert selbst dabei
  herrauskommen.  Die Idenitaet ist die Funktion, die Werte in sich
  selbst ueberfuert.

  #+begin_src scheme
    (define (id x) x)
  #+end_src

  Fuer Listen erwarten wir das intuitiv von der =map=-Funktion:

  #+begin_src scheme
        (map id (list 1 2 3 4))
    <-> (list (id 1) (id 2) (id 3) (id 4))
    <-> (list 1 2 3 4)
  #+end_src

  Die zweite Functorregel sagt aus, dass es keine Rolle spielen darf,
  ob wir zweimal =fmap= auf einen Wert anwenden (erst =f=, dann =g=),
  oder ob wir die beiden Funktionen verketten und dann nur einmal
  =fmap= anwenden.  Die =compose= Funktion ist folgendermasse definiert.

  #+begin_src scheme
    (define (compose g f)
      (lambda (x)
        (g (f x))))
  #+end_src

  Noch einmal am Beispiel von Listen:

  #+begin_src scheme
        (map 2* (map 1+ (list 1 2 3)))
    <-> (map 2* (list (1+ 1) (1+ 2) (1+ 3)))
    <-> (list (2* (1+ 1)) (2* (1+ 2)) (2* (1+ 3)))
    <-> (list ((compose 2* 1+) 1) ((compose 2* 1+) 2) ((compose 2* 1+) 3)
    <-> (map (compose 2* 1+) (list 1 2 3))
  #+end_src

  Wir haben bereits Beispiele fuer Functors gesehen: Listen und
  Baeume.  Dabei ist die =map=-Funktion fuer Listen auch die
  =fmap=-Funktion von Functors.  Ein weiteres Beispiel fuer Functors
  ist der Datentyp =maybe=.

** Beispiel: Maybe
   Manchmal haben wir es mit Berechnungen zutun, die kein Ergebnis
   liefern.  Ein Beispiel dafuer, waere die Funktion =div=, die 2
   Zahlen =a= und =b= nimmt und das Ergebnis der Division =a= / =b=
   zurueck gibt.

   Falls =b= gleich =0= ist, ist diese Operation nicht definiert.  In
   vielen Programmiersprachen wird dieses Problem durch Exceptions
   behandelt, andere Sprachen geben im Fehlerfall einfach den
   =0=-Zeiger zurueck und setzen eine Fehlervariable auf eine
   speziellen Fehlercode.

   Wir wollen uns einmal anschauen, wie wir eine potentiell
   ergebnislose Operation ohne diese Spezialwerkzeuge behandeln
   koennen.  Dazu benoetigen wir eine Art Behaelter, der entweder
   nichts (=nothing=) oder genau einen Wert (=just VALUE=) enthalten
   kann.  Wir muessen irgendwie Werte in diesen Behaelter tun koenne
   und auch wieder extrahieren koennen.  Dazu definieren wir folgende
   Regeln:

   * =(nothing? nothing) = #t=
   * =(nothing? (just x)) = #f=
   * =(just? nothing) = #f=
   * =(just? (just x)) = #t=
   * =(maybe x nothing) = x=
   * =(maybe x (just y)) = y=
   * =(from-just nothing) = UNDEFINED=
   * =(from-just (just x)) = x=

   Wir koennen mit diesen Operationen nun die =div=-Funktion
   definieren:

   #+begin_src scheme
     (define (div x y)
       (if (equal? y 0)
           nothing
           (just (/ x y))))
   #+end_src

   Stellen wir uns nun vor, dass wir das Ergebnis weiter verwenden
   wollen, in dem wir eine Funktion definieren, die eine Zahl das
   Reziproke einer Zahl findet (d.h. 1/x) und dann 1 hinzu addiert.

   #+begin_src scheme
     (define (rezi-and-add n)
       (let ((rezi (div 1 n)))
         (if (nothing? rezi)
             nothing
             (just (+ 1 (from-just rezi))))))
   #+end_src

   Diese erste Implementation sieht irgendwie umstaendlich aus.  Wir
   entpacken das Ergebnis der division nur, um es danach wieder zu
   verpacken, ausserdem muessen wir uns explizit um den Fehlerfall
   kuemmern.  Was wir brauchen, ist eine Funktion, die einen
   =maybe=-Wert nimmt und eine Operation darauf anwendet, sofern der
   Wert nicht leer ist.  Wir nennen diese Funktion =mmap= (MaybeMAP).
   Diese Funktion soll die folgenden Regeln befolgen:

   * =(mmap f nothing) = nothing=
   * =(mmap f (just x)) = (just (f x))=

   Mithilfe dieser Funktion koennen wir die =rezi-and-add=-Funktion
   viel einfacher implementieren:

   #+begin_src scheme
     (define (rezi-and-add n)
       (mmap 1+ (div 1 n)))
   #+end_src

   Diese zweite verbesserte Version hat die selbe Funktionalitaet
   ohne, dass wir uns explizit um den Fehlerfall kuemmern muessen.

   Implementieren wir nun die interne Repraesentation unseres neuen
   Datentyps.

   #+caption: =<<definition-maybe>>=
   #+name: definition-maybe
   #+begin_src scheme
     (define (just val)
       (cons 'just
             val))

     (define nothing
       (cons 'nothing #nil))

     (define (just? mval)
       (equal? (car mval) 'just))

     (define (nothing? mval)
       (equal? (car mval) 'nothing))

     (define (maybe alt mval)
       (if (just? mval)
           (cdr mval)
           alt))

     (define (from-just mval)
       (if (just? mval)
           (cdr mval)
           (error "FROM-JUST: cannot extract value from nothing" mval)))

     (define (mmap fun mval)
       (if (just? mval)
           (just (fun (from-just mval)))
           nothing))
   #+end_src

   Wir koennen nun eine kleine Functorbibliothek erstellen.  Ziel ist
   es, eine =fmap=-Funktion zu schreiben, die auf Listen, Maybewerten,
   Baeumen und eventuell noch anderen Datenstrukturen operieren kann.

* Data directed programming
  Stellen wir uns vor, dass wir eine Bibliothek schreiben wollen, die
  ein einheitliches Interface fuer den Umgang mit Baeumen, Listen und
  Doppellisten ermoeglichen soll.  Wir koennen zum Beispiel fuer alle
  drei Datentypen =map= und =foldl= definieren.  Falls wir es
  schaffen, eine einzige =foldl= Funktion zu schreiben, bekommen wir
  automatisch eine =length=-Funktion "for free".  Um dies zu
  bewerkstelligen, muessen wir irgendwie entscheiden koennen, mit
  welchem Datentyp wir es zu tun haben.  Dazu nutzen "type tags".

** Tagged data
   #+caption: =<<definition-type-tags>>=
   #+name: definition-type-tags
   #+begin_src scheme
     (define (attach-tag type-tag value)
       (cons type-tag value))

     (define (get-tagged-type val)
       (cond ((pair? val) (car val))
             (else (error "GET-TAGGED-TYPE: not a tagged value" val))))

     (define (get-tagged-value val)
       (cond ((pair? val) (cdr val))
             (else (error "GET-TAGGED-VALUE: not a tagged value" val))))
   #+end_src

   Jetzt muessen wir neue Konstruktoren fuer unsere Datentypen
   definieren, die unsere type tags benutzen.

   #+caption: =<<definition-tagged-list>>=
   #+name: definition-tagged-list
   #+begin_src scheme
     (define (get-list-internal xs)
       (if (eq? (get-tagged-type xs) 'list)
           (get-tagged-value xs)
           (error "GET-LIST-INTERNAL: value is not a list" xs)))

     (define (tail xs)
       (cdr (get-list-internal xs)))

     (define (head xs)
       (car (get-list-internal xs)))

     (define empty-list
       (attach-tag 'list #nil))

     (define (empty? l)
       (null? (get-list-internal l)))

     (define (prepend x xs)
       (attach-tag 'list
                   (cons x
                         xs)))

     (define (init xs)
       (cond ((empty? xs) (error "INIT: list is empty" xs))
             ((empty? (tail xs)) empty-list)
             (else (prepend (head xs)
                            (init (tail xs))))))

     (define (last xs)
       (cond ((empty? xs) (error "LAST: list is empty" xs))
             ((empty? (tail xs)) (head xs))
             (else (last (tail xs)))))

     (define (reverse xs)
       (define (iter accu rest)
         (cond ((empty? rest) accu)
               (else (iter (prepend (head rest) accu)
                           (tail rest)))))
       (iter empty-list xs))

     (define (tagged-list . xs)
       (define (iter ls)
         (cond ((null? ls) empty-list)
               (else (prepend (car ls) (iter (cdr ls))))))
       (iter xs))
   #+end_src

   #+caption: =<<definition-tagged-tree>>=
   #+name: definition-tagged-tree
   #+begin_src scheme
     (define leaf
       (attach-tag 'tree 'leaf))

     (define (branch value left right)
       (attach-tag 'tree
                   (list value left right)))

     (define (get-tree-internal t)
       (if (eq? (get-tagged-type t) 'tree)
           (get-tagged-value t)
           (error "GET-LEAF-INTERNAL: value is not a tree" t)))

     (define (leaf? t)
       (eq? t leaf))

     (define (branch? t)
       (not (leaf? t)))

     (define (left t)
       (if (branch? t)
           (cadr (get-tree-internal t))
           (error "LEFT: tree is a leaf" t)))

     (define (right t)
       (if (branch? t)
           (caddr (get-tree-internal t))
           (error "RIGHT: tree is a leaf" t)))

     (define (branch-value t)
       (if (branch? t)
           (car (get-tree-internal t))
           (error "BRANCH-VALUE: tree is a leaf" t)))

     (define (tree-add-elem smaller-or-equal t x)
       (if (leaf? t)
           (branch x leaf leaf)
           (if (smaller-or-equal x (branch-value t))
               (branch (branch-value t)
                       (tree-add-elem smaller-or-equal
                                      (left t)
                                      x)
                       (right t))
               (branch (branch-value t)
                       (left t)
                       (tree-add-elem smaller-or-equal
                                      (right t)
                                      x)))))

     (define (tree-from-list smaller-or-equal xs)
       (define (iter accu rest)
         (if (empty? rest)
             accu
             (iter (tree-add-elem smaller-or-equal accu (head rest))
                   (tail rest))))
       (iter leaf xs))
   #+end_src

   #+caption: =<<definition-tagged-double-list>>=
   #+name: definition-tagged-double-list
   #+begin_src scheme
     (define empty-dlist
       (attach-tag 'dlist
                   (list empty-list empty-list)))

     (define (get-dlist-internal dl)
       (if (eq? (get-tagged-type dl) 'dlist)
           (get-tagged-value dl)
           (error "GET-DLIST-INTERNAL: value is not a double list" dl)))

     (define (dprepend val dl)
       (let* ((intern (get-dlist-internal dl))
              (front (car intern))
              (back (cadr intern)))
         (attach-tag 'dlist
                       (list (prepend val front)
                             back))))

     (define (dappend dl val)
       (let* ((intern (get-dlist-internal dl))
              (front (car intern))
              (back (cadr intern)))
         (attach-tag 'dlist
                       (list front
                             (prepend val back)))))

     (define (dtail dl)
       (let* ((intern (get-dlist-internal dl))
              (front (car intern))
              (back (cadr intern)))
         (cond ((not (empty? front)) (attach-tag 'dlist
                                                 (cons (tail front)
                                                       back)))
               (else (attach-tag 'dlist
                                 (cons (tail (reverse back))
                                       empty-list))))))

     (define (dinit dl)
       (let* ((intern (get-dlist-internal dl))
              (front (car intern))
              (back (cadr intern)))
         (cond ((not (empty? back)) (attach-tag 'dlist
                                                (cons front
                                                      (tail back))))
               (else (attach-tag 'dlist
                                 (cons empty-list
                                       (tail (reverse front))))))))

     (define (dhead dl)
       (let* ((intern (get-dlist-internal dl))
              (front (car intern))
              (back (cadr intern)))
         (cond ((not (empty? front)) (head front))
               (else (last back)))))

     (define (dlast dl)
       (let* ((intern (get-dlist-internal dl))
              (front (car intern))
              (back (cadr intern)))
         (cond ((not (empty? back)) (head back))
               (else (last front)))))
   #+end_src

   Nun koennen wir eine entsprechende =map=-Funktion definieren.

   #+begin_src scheme :noweb no-export :tangle examples/map-03.scm
     <<definition-type-tags>>
     <<definition-tagged-list>>
     <<definition-tagged-tree>>
     <<definition-tagged-double-list>>

     (define (map fun container)
       (define (lmap fun l)
         (if (empty? l)
             empty-list
             (prepend (fun (head l))
                      (lmap fun (tail l)))))
       (define (tmap fun t)
         (if (leaf? t)
             leaf
             (branch (fun (branch-value t))
                     (tmap fun (left t))
                     (tmap fun (right t)))))
       (define (dmap fun dl)
         (let* ((intern (get-dlist-internal dl))
                (front (car intern))
                (back (cadr intern)))
           (attach-tag 'dlist
                       (cons (lmap fun front)
                             (lmap fun back)))))
       (cond ((eq? (get-tagged-type container) 'list) (lmap fun container))
             ((eq? (get-tagged-type container) 'tree) (tmap fun container))
             ((eq? (get-tagged-type container) 'dlist) (dmap fun container))
             (else (error "MAP: unknown type" container))))
   #+end_src

   Diese Definition ermoeglicht nun ein einheitliches "Interface" fuer
   alle Datentypen, die die =map=-Operation unterstuetzen.  Ein
   entscheidender Nachteil ist dabei jedoch, dass wir jedesmal, wenn
   wir einen neuen Datentypen hinzufuegen wollen, die =map=-Funktion
   selbst editieren muessen.  Das fuehrt dazu, dass unser kleines Modul
   nicht gut erweitert werden kann.

** Type lookup tables
   Ein modularerer Ansatz fuer "ueberladene Funktionen" ist das
   Benutzen einer Tabelle, in der hinterlegt ist, welche Funktion fuer
   welchen Typen benutzt werden soll.  Wir koennen uns eine Tabelle
   folgendermassen vorstellen:

   | Operation | list     | tree     | dlist    |
   |-----------+----------+----------+----------|
   | map       | =lmap=   | =tmap=   | =dmap=   |
   | foldl     | =lfoldl= | =tfoldl= | =dfoldl= |

   Wenn ein neuer Datentype geschrieben wird, der =map= unterstuetzt,
   muss er einfach nur der Tabelle hinzugefuegt werden.

   #+caption: =examples/map-04.scm=
   #+begin_src scheme :tangle examples/map-04.scm :noweb no-export
     <<definition-type-tags>>
     <<definition-tagged-list>>
     <<definition-tagged-tree>>
     <<definition-tagged-double-list>>

     (define map-lookup-table (make-hash-table))

     (define (map fun container)
       (let ((op (hashq-ref map-lookup-table
                            (get-tagged-type container))))
         (if op
             (op fun container)
             (error "MAP: not defined for this type"
                    (get-tagged-type container)))))

     (define (mmap fun l)
       (if (empty? l)
           empty-list
           (prepend (fun (head l)) (mmap fun (tail l)))))

     (define (tmap fun t)
       (if (leaf? t)
           leaf
           (branch (fun (branch-value t))
                   (tmap fun (left t))
                   (tmap fun (right t)))))

     (define (dmap fun dl)
       (let* ((intern (get-dlist-internal dl))
              (front (car intern))
              (back (cadr intern)))
         (attach-tag 'dlist
                     (list (map fun front)
                           (map fun back)))))

     (hashq-set! map-lookup-table 'list mmap)
     (hashq-set! map-lookup-table 'dlist dmap)
     (hashq-set! map-lookup-table 'tree tmap)
   #+end_src

** Veraenderliche Daten
   Im obigen Programmbeispiel wird der Befehl =hashq-set!= verwendet.
   Dieser Befehl nimmt eine Hashmap entgegen und nimmt ein Update vor.
   Hier sollten wir ein wenig stutzig werden, da bisher einmal
   erzeugte Daten nicht mehr veraendert werden konnten, mit anderen
   Worten: =hashq-set!= ist eine Zuweisungsanweisung.

   Wir sollten uns darueber im Klaren sein, sein, dass wir sehr
   vorsichtig sein muessen, wenn wir veraenderliche Daten haben, da
   viele nette Eigenschaften funktionaler Programmierung verloren
   gehen, wenn wir Zuweisungen erlauben.  Darunter faellt unter
   anderem, dass wir nicht mehr davon ausgehen koennen, dass eine
   Funktion, aufgerufen mit bestimmten Argumenten, immer das selbe
   Ergebnis produziert, egal wo sie im Programm aufgerufen wird.

   Im weiteren Verlauf dieses Textes werden wir Zuweisungen nur fuer 2
   Dingen verwenden: "data directed programming" und "memoization"
   (das werden wir noch kennenlernen).  Dies wird den imperativen
   Einfluss auf unsere Programme gering halten, aber trotzdem flexibel
   genug sein, um spannende Konzepte kennenzulernen.

** GOOPS
   Guile Scheme stellt bereits eine Infrastruktur fuer genau solche
   Anwendungsfaelle bereit, GOOPS.  Der Name leitet sich (irgendwie) von
   objektorientierter Programmierung ab.

   Wenn wir GOOPS benutzen wollen, muessen wir es ersteinmal importieren:
   #+name: goops-example-imports
   #+caption: =<<goops-example-imports>>=
   #+begin_src scheme
     (use-modules (oop goops))
   #+end_src

   Um jetzt unser Funktorinterface zu implementieren, muessen wir eine
   generische Funktion definieren, die die "mapping"-Funktion repraesentiert
   #+name: goops-example-defs
   #+caption: =<<goops-example-defs>>=
   #+begin_src scheme
     (define-generic fmap)
   #+end_src

   Nun erstellen wir eine Klasse, wobei Klasse hier sehr nah dran ist, an der
   Javadefinition fuer Klasse.
   #+name: goops-example-maybe-def
   #+caption: =<<goops-example-maybe-def>>=
   #+begin_src scheme
     (define-class <maybe> ()
       (is-set #:getter maybe-is-set
               #:init-keyword #:is-set)
       (value #:getter maybe-value
              #:init-keyword #:value))
   #+end_src

   Wir wollen nun Konstruktoren definieren.  Der primitive
   Konstruktor, den jede Klasses von Hause aus besitzt, ist =make=.
   Wir wollen aber eigene Konstruktoren definieren.

   #+name: goops-example-maybe-methods
   #+caption: =<<goops-example-maybe-methods>>=
   #+begin_src scheme
     (define (make-just val)
       (make <maybe> #:is-set #t #:value val))
     (define nothing
       (make <maybe> #:is-set #f #:value #f))
   #+end_src

   Wir haben jetzt die Datenfelder und die Konstruktoren von =<maybe>=
   definiert, aber noch keine Methoden.  Anders als in Java und
   Co. werden Methoden nicht als Attribute an Klassen angehaengt,
   sonder ueber Funktionssignatur deklariert.

   #+name: goops-example-maybe-methods
   #+caption: =+<<goops-example-maybe-methods>>=
   #+begin_src scheme
     (define-method (is-just (x <maybe>))
       (maybe-is-set x))
   #+end_src

   Die =is-nothing=-Funktion ist trivial, da wir einfach nur das
   Ergebnis von =is-just= negieren muessen.

   #+name: goops-example-maybe-methods
   #+caption: =+<<goops-example-maybe-methods>>=
   #+begin_src scheme
     (define-method (is-nothing (x <maybe>))
       (not (is-just x)))
   #+end_src

   Unsere =fmap=-Funktion wird nun auch als Methode von =<maybe>=
   implementiert.
   #+name: goops-example-maybe-methods
   #+caption: =+<<goops-example-maybe-methods>>=
   #+begin_src scheme
     (define-method (fmap fun (x <maybe>))
       (if (maybe-is-set x)
           (make-just (fun (maybe-value x)))
           x))
   #+end_src

   Nun muessen wir nur noch alles zu einem Modul zusammenfassen:
   #+begin_src scheme :noweb yes :tangle examples/goops-example.scm
     <<goops-example-imports>>
     <<goops-example-defs>>
     <<goops-example-maybe-def>>
     <<goops-example-maybe-methods>>
   #+end_src 

*** Objektorientierung
    Objektorientierung ist eine Spezialform von data directed
    programming.  Die Methoden, fuer ein Datensatz ein gueltiges
    Argument darstellen, werden oft Objektmethoden genannt.  In den
    meisten objektorientierten Sprachen werden diese Methoden so
    definiert, dass ein Parameter der Methode das Objekt ist, "auf das
    die Methode angewendet" werden soll.  In Python geschieht das
    durch das Argument "self", in Java und Javascript ist es "this".
    Aus dieser Notation ergeben sich haeufig seltsame Streitigkeiten,
    welche Method zu welcher Objektklasse gehoert.

    Nehmen wir einmal an, wir haben eine Klasse =Form=, die
    geometrische Formen abbildet und eine Klasse =Leinwand=, auf die
    diese Formen "gemalt" werden koennen.  Ist die Methode "male Form
    auf Leinwand" nun eine Methode von =Form=, die als Argument eine
    Leinwand entgegen nimmt, oder eine Methode der Klasse =Leinwand=,
    die eine Form entgegen nimmt.  Man findet Vertreter der eine, als
    auch der anderen Interpretation.

    Dieses Problem ist ein guter Hinweis darauf, die Implementation
    von "OO" durch implizite Argumente und "Klassenmethoden", die
    als 

* Shared variables
  Mit der methode =set!= kann der Wert einer Variable veraendert werden.
  #+begin_src scheme
    (define n 0)
    (set! n 1)
    (display n)
    ;; 1
  #+end_src

  Um die selbe Variable an verschiedenen stellen in unserem Program
  veraendern zu koennen, nutzen wir =set!=.
  #+begin_src scheme
    ;; Dieses Programm soll es ermoeglichen, einen zentralen Kontostand zu
    ;; verwalten

    ;; Wir benoetigen zwei funktionen: einzahlen und kontostand.
    (define deposit #f) ;; einzahlen
    (define get-balance #f) ;; kontostand

    (let ((balance 0)) ;; der kontostand wird mit 0 initialisiert
      (set! get-balance
        (lambda () balance))
      (set! desposit
        (lambda (amount)
          (set! balance (+ balance amount)))))

    (get-balance) ;; 0
    (deposit 5)
    (get-balance) ;; 5
    (deposit 10)
    (get-balance) ;; 15
  #+end_src

* Beispiel: web server
  Wie die meisten modernen Sprachen, stellt GNU Guile eine
  Webserverimplementation bereit, mit der beliebige Daten zwischen
  Client und Server ausgetauscht werden koennen.  Der entsprechende Code ist im Modul
  =web server= zu finden.

  #+caption: =<<server-imports>>=
  #+name: server-imports
  #+begin_src scheme
    (use-modules (web server))
  #+end_src

  Das Modul stellt eine Funktion =run-server= bereit, die den
  Webserver startet.  =run-server= nimmt ein Pflichtargument entgegen,
  welches eine Funktion ist, wir nennen sie =handler=.

  #+caption: =<<server-run>>=
  #+name: server-run
  #+begin_src scheme
    (run-server handler)
  #+end_src

  Die =handler=-Funktion bearbeitet eingehende Requests und
  konstruiert (gueltige) Responses.  Sie muss zwei Parameter
  verstehen, wobei der erste Parameter den Request Header und der
  zweite Parameter den Request body repraesentiert.

  #+caption: =<<server-handler-def>>=
  #+name: server-handler-def
  #+begin_src scheme
    (define (handler request-header request-body)
      <<server-handler-implementation>>)
  #+end_src

  Um dem Interface des Webservers zu genuegen, muss die Funktion
  ausserdem zwei Argumente zurueck geben, nicht zu verwechseln mit
  einem Paar von zwei Werten.  Guile Scheme stellt die moeglichkeit
  bereit, dass eine Funktion mehrere Rueckgabewerte hat, dies wird
  ueber die =values=-Funktion realisiert, die zu den Grundfunktionen
  der Sprache gehoert.  Der erste Rueckgabewert repraesentiert den
  Response Header und der zweite Rueckgabewert den Response Body.

  #+caption: =<<server-handler-implementation>>=
  #+name: server-handler-implementation
  #+begin_src scheme
    (values
     <<server-response-header-implementation>>
     <<server-response-body-implementation>>)
  #+end_src

  Um den Response Header zu konstruieren, kann die
  =build-response=-Funktion aus dem Modul =web response= genutzt
  werden.

  #+caption: =<<server-imports>>=
  #+name: server-imports
  #+begin_src scheme
    (use-modules (web response))
  #+end_src

  #+caption: =<<server-response-header-implementation>>=
  #+name: server-response-header-implementation
  #+begin_src scheme
    (build-response #:code 200
                    #:headers `((content-type . (text/html))))
  #+end_src

  Die Implementation fuer den Response Body muss eine Funktion mit
  einem Argument sein.  Dieses Argument ist ein sogenannter Port, auf
  den die Ausgabe geschrieben werden muss.  Dazu kann zum Beispiel die
  =display=-Funktion benutzt werden.

  #+caption: =<<server-response-body-implementation>>=
  #+name: server-response-body-implementation
  #+begin_src scheme
    (lambda (port)
      (display "hello world" port))
  #+end_src

  Das vollstaendige Programm besteht dann aus den oben definierten
  Bestandteilen.

  #+begin_src scheme :noweb no-export :tangle examples/server1.scm :shebang "#!/usr/bin/env guile !#"
    <<server-imports>>

    <<server-handler-def>>

    <<server-run>>
  #+end_src

  Wenn das Programm =examples/server1.scm= ausgefuehrt wird, wird ein
  Webserver auf Port 8080 gestartet.  Bei einem Request liefert der
  Server ein HTML-Dokumen aus, in dem "hello world" steht.

* Quoting
  LISP eignet sich sehr gut fuer sogenanntes "meta programming", damit
  bezeichnet man das Schreiben und Manipulieren von Computerprogrammen
  durch Programme.  Jeder gueltige LISP-Ausdruck laesst sich als Liste
  darstellen.

  #+begin_src scheme :exports both
    (define exp (list '+ 1 2))
    (eval exp (interaction-environment))
  #+end_src

  Zum evaluieren des Codes muss der Interpreter wissen, in welcher
  Umgebung er den Code ausfuehren soll.  Die Funktion
  =interaction-environment= definiert eine Umgebung aehnlich zu der
  Umgebung in der REPL.

* GNU Free Documentation License

   GNU Free Documentation License
   Version 1.3, 3 November 2008


   Copyright (C) 2000, 2001, 2002, 2007, 2008 Free Software Foundation, Inc.
     <http://fsf.org/>
   Everyone is permitted to copy and distribute verbatim copies
   of this license document, but changing it is not allowed.

** PREAMBLE

   The purpose of this License is to make a manual, textbook, or other
   functional and useful document "free" in the sense of freedom: to
   assure everyone the effective freedom to copy and redistribute it,
   with or without modifying it, either commercially or noncommercially.
   Secondarily, this License preserves for the author and publisher a way
   to get credit for their work, while not being considered responsible
   for modifications made by others.

   This License is a kind of "copyleft", which means that derivative
   works of the document must themselves be free in the same sense.  It
   complements the GNU General Public License, which is a copyleft
   license designed for free software.

   We have designed this License in order to use it for manuals for free
   software, because free software needs free documentation: a free
   program should come with manuals providing the same freedoms that the
   software does.  But this License is not limited to software manuals;
   it can be used for any textual work, regardless of subject matter or
   whether it is published as a printed book.  We recommend this License
   principally for works whose purpose is instruction or reference.

** APPLICABILITY AND DEFINITIONS

   This License applies to any manual or other work, in any medium, that
   contains a notice placed by the copyright holder saying it can be
   distributed under the terms of this License.  Such a notice grants a
   world-wide, royalty-free license, unlimited in duration, to use that
   work under the conditions stated herein.  The "Document", below,
   refers to any such manual or work.  Any member of the public is a
   licensee, and is addressed as "you".  You accept the license if you
   copy, modify or distribute the work in a way requiring permission
   under copyright law.

   A "Modified Version" of the Document means any work containing the
   Document or a portion of it, either copied verbatim, or with
   modifications and/or translated into another language.

   A "Secondary Section" is a named appendix or a front-matter section of
   the Document that deals exclusively with the relationship of the
   publishers or authors of the Document to the Document's overall
   subject (or to related matters) and contains nothing that could fall
   directly within that overall subject.  (Thus, if the Document is in
   part a textbook of mathematics, a Secondary Section may not explain
   any mathematics.)  The relationship could be a matter of historical
   connection with the subject or with related matters, or of legal,
   commercial, philosophical, ethical or political position regarding
   them.

   The "Invariant Sections" are certain Secondary Sections whose titles
   are designated, as being those of Invariant Sections, in the notice
   that says that the Document is released under this License.  If a
   section does not fit the above definition of Secondary then it is not
   allowed to be designated as Invariant.  The Document may contain zero
   Invariant Sections.  If the Document does not identify any Invariant
   Sections then there are none.

   The "Cover Texts" are certain short passages of text that are listed,
   as Front-Cover Texts or Back-Cover Texts, in the notice that says that
   the Document is released under this License.  A Front-Cover Text may
   be at most 5 words, and a Back-Cover Text may be at most 25 words.

   A "Transparent" copy of the Document means a machine-readable copy,
   represented in a format whose specification is available to the
   general public, that is suitable for revising the document
   straightforwardly with generic text editors or (for images composed of
   pixels) generic paint programs or (for drawings) some widely available
   drawing editor, and that is suitable for input to text formatters or
   for automatic translation to a variety of formats suitable for input
   to text formatters.  A copy made in an otherwise Transparent file
   format whose markup, or absence of markup, has been arranged to thwart
   or discourage subsequent modification by readers is not Transparent.
   An image format is not Transparent if used for any substantial amount
   of text.  A copy that is not "Transparent" is called "Opaque".

   Examples of suitable formats for Transparent copies include plain
   ASCII without markup, Texinfo input format, LaTeX input format, SGML
   or XML using a publicly available DTD, and standard-conforming simple
   HTML, PostScript or PDF designed for human modification.  Examples of
   transparent image formats include PNG, XCF and JPG.  Opaque formats
   include proprietary formats that can be read and edited only by
   proprietary word processors, SGML or XML for which the DTD and/or
   processing tools are not generally available, and the
   machine-generated HTML, PostScript or PDF produced by some word
   processors for output purposes only.

   The "Title Page" means, for a printed book, the title page itself,
   plus such following pages as are needed to hold, legibly, the material
   this License requires to appear in the title page.  For works in
   formats which do not have any title page as such, "Title Page" means
   the text near the most prominent appearance of the work's title,
   preceding the beginning of the body of the text.

   The "publisher" means any person or entity that distributes copies of
   the Document to the public.

   A section "Entitled XYZ" means a named subunit of the Document whose
   title either is precisely XYZ or contains XYZ in parentheses following
   text that translates XYZ in another language.  (Here XYZ stands for a
   specific section name mentioned below, such as "Acknowledgements",
   "Dedications", "Endorsements", or "History".)  To "Preserve the Title"
   of such a section when you modify the Document means that it remains a
   section "Entitled XYZ" according to this definition.

   The Document may include Warranty Disclaimers next to the notice which
   states that this License applies to the Document.  These Warranty
   Disclaimers are considered to be included by reference in this
   License, but only as regards disclaiming warranties: any other
   implication that these Warranty Disclaimers may have is void and has
   no effect on the meaning of this License.

** VERBATIM COPYING

   You may copy and distribute the Document in any medium, either
   commercially or noncommercially, provided that this License, the
   copyright notices, and the license notice saying this License applies
   to the Document are reproduced in all copies, and that you add no
   other conditions whatsoever to those of this License.  You may not use
   technical measures to obstruct or control the reading or further
   copying of the copies you make or distribute.  However, you may accept
   compensation in exchange for copies.  If you distribute a large enough
   number of copies you must also follow the conditions in section 3.

   You may also lend copies, under the same conditions stated above, and
   you may publicly display copies.

** COPYING IN QUANTITY

   If you publish printed copies (or copies in media that commonly have
   printed covers) of the Document, numbering more than 100, and the
   Document's license notice requires Cover Texts, you must enclose the
   copies in covers that carry, clearly and legibly, all these Cover
   Texts: Front-Cover Texts on the front cover, and Back-Cover Texts on
   the back cover.  Both covers must also clearly and legibly identify
   you as the publisher of these copies.  The front cover must present
   the full title with all words of the title equally prominent and
   visible.  You may add other material on the covers in addition.
   Copying with changes limited to the covers, as long as they preserve
   the title of the Document and satisfy these conditions, can be treated
   as verbatim copying in other respects.

   If the required texts for either cover are too voluminous to fit
   legibly, you should put the first ones listed (as many as fit
   reasonably) on the actual cover, and continue the rest onto adjacent
   pages.

   If you publish or distribute Opaque copies of the Document numbering
   more than 100, you must either include a machine-readable Transparent
   copy along with each Opaque copy, or state in or with each Opaque copy
   a computer-network location from which the general network-using
   public has access to download using public-standard network protocols
   a complete Transparent copy of the Document, free of added material.
   If you use the latter option, you must take reasonably prudent steps,
   when you begin distribution of Opaque copies in quantity, to ensure
   that this Transparent copy will remain thus accessible at the stated
   location until at least one year after the last time you distribute an
   Opaque copy (directly or through your agents or retailers) of that
   edition to the public.

   It is requested, but not required, that you contact the authors of the
   Document well before redistributing any large number of copies, to
   give them a chance to provide you with an updated version of the
   Document.

** MODIFICATIONS

   You may copy and distribute a Modified Version of the Document under
   the conditions of sections 2 and 3 above, provided that you release
   the Modified Version under precisely this License, with the Modified
   Version filling the role of the Document, thus licensing distribution
   and modification of the Modified Version to whoever possesses a copy
   of it.  In addition, you must do these things in the Modified Version:

   * A. :: Use in the Title Page (and on the covers, if any) a title
           distinct from that of the Document, and from those of
           previous versions (which should, if there were any, be
           listed in the History section of the Document).  You may
           use the same title as a previous version if the original
           publisher of that version gives permission.
   * B. :: List on the Title Page, as authors, one or more persons or
           entities responsible for authorship of the modifications in
           the Modified Version, together with at least five of the
           principal authors of the Document (all of its principal
           authors, if it has fewer than five), unless they release
           you from this requirement.
   * C. :: State on the Title page the name of the publisher of the
           Modified Version, as the publisher.
   * D. :: Preserve all the copyright notices of the Document.
   * E. :: Add an appropriate copyright notice for your modifications
           adjacent to the other copyright notices.
   * F. :: Include, immediately after the copyright notices, a license
           notice giving the public permission to use the Modified
           Version under the terms of this License, in the form shown
           in the Addendum below.
   * G. :: Preserve in that license notice the full lists of Invariant
           Sections and required Cover Texts given in the Document's
           license notice.
   * H. :: Include an unaltered copy of this License.
   * I. :: Preserve the section Entitled "History", Preserve its
           Title, and add to it an item stating at least the title,
           year, new authors, and publisher of the Modified Version as
           given on the Title Page.  If there is no section Entitled
           "History" in the Document, create one stating the title,
           year, authors, and publisher of the Document as given on
           its Title Page, then add an item describing the Modified
           Version as stated in the previous sentence.
   * J. :: Preserve the network location, if any, given in the
           Document for public access to a Transparent copy of the
           Document, and likewise the network locations given in the
           Document for previous versions it was based on.  These may
           be placed in the "History" section.  You may omit a network
           location for a work that was published at least four years
           before the Document itself, or if the original publisher of
           the version it refers to gives permission.
   * K. :: For any section Entitled "Acknowledgements" or
           "Dedications", Preserve the Title of the section, and
           preserve in the section all the substance and tone of each
           of the contributor acknowledgements and/or dedications
           given therein.
   * L. :: Preserve all the Invariant Sections of the Document,
           unaltered in their text and in their titles.  Section
           numbers or the equivalent are not considered part of the
           section titles.
   * M. :: Delete any section Entitled "Endorsements".  Such a section
           may not be included in the Modified Version.
   * N. :: Do not retitle any existing section to be Entitled
           "Endorsements" or to conflict in title with any Invariant
           Section.
   * O. :: Preserve any Warranty Disclaimers.

   If the Modified Version includes new front-matter sections or
   appendices that qualify as Secondary Sections and contain no material
   copied from the Document, you may at your option designate some or all
   of these sections as invariant.  To do this, add their titles to the
   list of Invariant Sections in the Modified Version's license notice.
   These titles must be distinct from any other section titles.

   You may add a section Entitled "Endorsements", provided it contains
   nothing but endorsements of your Modified Version by various
   parties--for example, statements of peer review or that the text has
   been approved by an organization as the authoritative definition of a
   standard.

   You may add a passage of up to five words as a Front-Cover Text, and a
   passage of up to 25 words as a Back-Cover Text, to the end of the list
   of Cover Texts in the Modified Version.  Only one passage of
   Front-Cover Text and one of Back-Cover Text may be added by (or
   through arrangements made by) any one entity.  If the Document already
   includes a cover text for the same cover, previously added by you or
   by arrangement made by the same entity you are acting on behalf of,
   you may not add another; but you may replace the old one, on explicit
   permission from the previous publisher that added the old one.

   The author(s) and publisher(s) of the Document do not by this License
   give permission to use their names for publicity for or to assert or
   imply endorsement of any Modified Version.

** COMBINING DOCUMENTS

   You may combine the Document with other documents released under this
   License, under the terms defined in section 4 above for modified
   versions, provided that you include in the combination all of the
   Invariant Sections of all of the original documents, unmodified, and
   list them all as Invariant Sections of your combined work in its
   license notice, and that you preserve all their Warranty Disclaimers.

   The combined work need only contain one copy of this License, and
   multiple identical Invariant Sections may be replaced with a single
   copy.  If there are multiple Invariant Sections with the same name but
   different contents, make the title of each such section unique by
   adding at the end of it, in parentheses, the name of the original
   author or publisher of that section if known, or else a unique number.
   Make the same adjustment to the section titles in the list of
   Invariant Sections in the license notice of the combined work.

   In the combination, you must combine any sections Entitled "History"
   in the various original documents, forming one section Entitled
   "History"; likewise combine any sections Entitled "Acknowledgements",
   and any sections Entitled "Dedications".  You must delete all sections
   Entitled "Endorsements".

** COLLECTIONS OF DOCUMENTS

   You may make a collection consisting of the Document and other
   documents released under this License, and replace the individual
   copies of this License in the various documents with a single copy
   that is included in the collection, provided that you follow the rules
   of this License for verbatim copying of each of the documents in all
   other respects.

   You may extract a single document from such a collection, and
   distribute it individually under this License, provided you insert a
   copy of this License into the extracted document, and follow this
   License in all other respects regarding verbatim copying of that
   document.

** AGGREGATION WITH INDEPENDENT WORKS

   A compilation of the Document or its derivatives with other separate
   and independent documents or works, in or on a volume of a storage or
   distribution medium, is called an "aggregate" if the copyright
   resulting from the compilation is not used to limit the legal rights
   of the compilation's users beyond what the individual works permit.
   When the Document is included in an aggregate, this License does not
   apply to the other works in the aggregate which are not themselves
   derivative works of the Document.

   If the Cover Text requirement of section 3 is applicable to these
   copies of the Document, then if the Document is less than one half of
   the entire aggregate, the Document's Cover Texts may be placed on
   covers that bracket the Document within the aggregate, or the
   electronic equivalent of covers if the Document is in electronic form.
   Otherwise they must appear on printed covers that bracket the whole
   aggregate.

** TRANSLATION

   Translation is considered a kind of modification, so you may
   distribute translations of the Document under the terms of section 4.
   Replacing Invariant Sections with translations requires special
   permission from their copyright holders, but you may include
   translations of some or all Invariant Sections in addition to the
   original versions of these Invariant Sections.  You may include a
   translation of this License, and all the license notices in the
   Document, and any Warranty Disclaimers, provided that you also include
   the original English version of this License and the original versions
   of those notices and disclaimers.  In case of a disagreement between
   the translation and the original version of this License or a notice
   or disclaimer, the original version will prevail.

   If a section in the Document is Entitled "Acknowledgements",
   "Dedications", or "History", the requirement (section 4) to Preserve
   its Title (section 1) will typically require changing the actual
   title.

** TERMINATION

   You may not copy, modify, sublicense, or distribute the Document
   except as expressly provided under this License.  Any attempt
   otherwise to copy, modify, sublicense, or distribute it is void, and
   will automatically terminate your rights under this License.

   However, if you cease all violation of this License, then your license
   from a particular copyright holder is reinstated (a) provisionally,
   unless and until the copyright holder explicitly and finally
   terminates your license, and (b) permanently, if the copyright holder
   fails to notify you of the violation by some reasonable means prior to
   60 days after the cessation.

   Moreover, your license from a particular copyright holder is
   reinstated permanently if the copyright holder notifies you of the
   violation by some reasonable means, this is the first time you have
   received notice of violation of this License (for any work) from that
   copyright holder, and you cure the violation prior to 30 days after
   your receipt of the notice.

   Termination of your rights under this section does not terminate the
   licenses of parties who have received copies or rights from you under
   this License.  If your rights have been terminated and not permanently
   reinstated, receipt of a copy of some or all of the same material does
   not give you any rights to use it.

** FUTURE REVISIONS OF THIS LICENSE

   The Free Software Foundation may publish new, revised versions of the
   GNU Free Documentation License from time to time.  Such new versions
   will be similar in spirit to the present version, but may differ in
   detail to address new problems or concerns.  See
   [[http://www.gnu.org/copyleft/]].

   Each version of the License is given a distinguishing version number.
   If the Document specifies that a particular numbered version of this
   License "or any later version" applies to it, you have the option of
   following the terms and conditions either of that specified version or
   of any later version that has been published (not as a draft) by the
   Free Software Foundation.  If the Document does not specify a version
   number of this License, you may choose any version ever published (not
   as a draft) by the Free Software Foundation.  If the Document
   specifies that a proxy can decide which future versions of this
   License can be used, that proxy's public statement of acceptance of a
   version permanently authorizes you to choose that version for the
   Document.

** RELICENSING

   "Massive Multiauthor Collaboration Site" (or "MMC Site") means any
   World Wide Web server that publishes copyrightable works and also
   provides prominent facilities for anybody to edit those works.  A
   public wiki that anybody can edit is an example of such a server.  A
   "Massive Multiauthor Collaboration" (or "MMC") contained in the site
   means any set of copyrightable works thus published on the MMC site.

   "CC-BY-SA" means the Creative Commons Attribution-Share Alike 3.0
   license published by Creative Commons Corporation, a not-for-profit
   corporation with a principal place of business in San Francisco,
   California, as well as future copyleft versions of that license
   published by that same organization.

   "Incorporate" means to publish or republish a Document, in whole or in
   part, as part of another Document.

   An MMC is "eligible for relicensing" if it is licensed under this
   License, and if all works that were first published under this License
   somewhere other than this MMC, and subsequently incorporated in whole or
   in part into the MMC, (1) had no cover texts or invariant sections, and
   (2) were thus incorporated prior to November 1, 2008.

   The operator of an MMC Site may republish an MMC contained in the site
   under CC-BY-SA on the same site at any time before August 1, 2009,
   provided the MMC is eligible for relicensing.


** ADDENDUM: How to use this License for your documents

   To use this License in a document you have written, include a copy of
   the License in the document and put the following copyright and
   license notices just after the title page:

   #+begin_example
     Copyright (c)  YEAR  YOUR NAME.
     Permission is granted to copy, distribute and/or modify this document
     under the terms of the GNU Free Documentation License, Version 1.3
     or any later version published by the Free Software Foundation;
     with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts.
     A copy of the license is included in the section entitled "GNU
     Free Documentation License".
   #+end_example

   If you have Invariant Sections, Front-Cover Texts and Back-Cover Texts,
   replace the "with...Texts." line with this:

   #+begin_example
     with the Invariant Sections being LIST THEIR TITLES, with the
     Front-Cover Texts being LIST, and with the Back-Cover Texts being LIST.
   #+end_example

   If you have Invariant Sections without Cover Texts, or some other
   combination of the three, merge those two alternatives to suit the
   situation.

   If your document contains nontrivial examples of program code, we
   recommend releasing these examples in parallel under your choice of
   free software license, such as the GNU General Public License,
   to permit their use in free software.

About

Materials for a LISP class (in german)

Resources

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages