EMZETT.
Login

Kurz: (zeige ((zweimal 1+) 5)) (zeige ((kompose 1+ (lambda (x) (* x 10))) 4)) (zeige (map (addierer 100) ‘(1 2 3))) (zeige (((curry2 +) 3) 4)) (zeige (apply map list ‘((1 2 3) (4 5 6)))) (zeige (map (lambda (f) (f 10)) (list 1+ 1-.

Teil des Kurses Scheme

Kapitel 4 von 8 im Kurs Scheme. Mit Fortschritt, Quiz und Zertifikat auf der Lernseite.

Funktionen sind Werte

(use-modules (srfi srfi-1))
(define (zeige x) (display x) (newline))
(define (zweimal f) (lambda (x) (f (f x))))
(define (kompose f g) (lambda (x) (f (g x))))
(define (addierer n) (lambda (x) (+ x n)))
(define (curry2 f) (lambda (a) (lambda (b) (f a b))))
 
(zeige ((zweimal 1+) 5))
(zeige ((kompose 1+ (lambda (x) (* x 10))) 4))
(zeige (map (addierer 100) '(1 2 3)))
(zeige (((curry2 +) 3) 4))
(zeige (apply map list '((1 2 3) (4 5 6))))
(zeige (map (lambda (f) (f 10)) (list 1+ 1- (lambda (x) (* x x)))))
(zeige (fold-right cons '() '(1 2 3)))
(zeige (fold cons '() '(1 2 3)))
(zeige (reduce + 0 '(1 2 3 4)))
(zeige (delete 2 '(1 2 3 2)))
(zeige (partition even? '(1 2 3 4 5)))
(zeige (any even? '(1 3 4)))
(zeige (every even? '(2 4)))
(zeige (find (lambda (x) (> x 3)) '(1 5 2 7)))
(zeige (append-map (lambda (x) (list x x)) '(1 2)))
(zeige (delete-duplicates '(1 2 2 3 3 3)))
(zeige (list-index even? '(1 3 4)))
(zeige (take '(1 2 3 4) 2))
(zeige (drop '(1 2 3 4) 2))
(zeige (last '(1 2 3)))

Ausgabe:

7
41
(101 102 103)
7
((1 4) (2 5) (3 6))
(11 9 100)
(1 2 3)
(3 2 1)
10
(1 3)
(2 4)
#t
#t
5
(1 1 2 2)
(1 2 3)
2
(1 2)
(3 4)
3

Closures und Zustand

(define (zeige x) (display x) (newline))
 
(define (make-zaehler)
  (let ((n 0))
    (lambda () (set! n (+ n 1)) n)))
 
(define a (make-zaehler))
(define b (make-zaehler))
(a) (a)
(zeige (list (a) (b)))
 
(define (make-konto stand)
  (lambda (nachricht . args)
    (case nachricht
      ((einzahlen) (set! stand (+ stand (car args))) stand)
      ((abheben)
       (if (> (car args) stand)
           "Nicht genug Guthaben"
           (begin (set! stand (- stand (car args))) stand)))
      ((stand) stand)
      (else "unbekannte Nachricht"))))
 
(define k (make-konto 100))
(zeige (k 'einzahlen 50))
(zeige (k 'abheben 30))
(zeige (k 'abheben 500))
(zeige (k 'stand))
 
(define (memoize f)
  (let ((cache (make-hash-table)))
    (lambda (n)
      (or (hash-ref cache n #f)
          (let ((wert (f n)))
            (hash-set! cache n wert)
            wert)))))
 
(define fib
  (memoize (lambda (n) (if (< n 2) n (+ (fib (- n 1)) (fib (- n 2)))))))
(zeige (fib 80))

Ausgabe:

(3 1)
150
120
Nicht genug Guthaben
120
23416728348467685

Closures und Nachrichten ('einzahlen) zeigen, wie man in Scheme Objekte aus Funktionen baut – eine Idee aus SICP.

Makros mit syntax-rules

(define (zeige x) (display x) (newline))
 
(define-syntax mein-unless
  (syntax-rules ()
    ((_ bedingung rumpf ...) (if bedingung #f (begin rumpf ...)))))
 
(define-syntax tausche!
  (syntax-rules ()
    ((_ a b) (let ((tmp a)) (set! a b) (set! b tmp)))))
 
(define-syntax wiederhole
  (syntax-rules ()
    ((_ n rumpf ...) (let schleife ((i 0)) (when (< i n) rumpf ... (schleife (+ i 1)))))))
 
(define-syntax mein-or
  (syntax-rules ()
    ((_) #f)
    ((_ e) e)
    ((_ e rest ...) (let ((t e)) (if t t (mein-or rest ...))))))
 
(zeige (mein-unless #f "läuft"))
(define p 1)
(define q 2)
(tausche! p q)
(zeige (list p q))
(wiederhole 3 (display "x "))
(newline)
(define tmp 99)
(define r 1)
(tausche! tmp r)
(zeige (list tmp r))
(zeige (mein-or #f #f 7))

Ausgabe:

l?uft
(2 1)
x x x
(1 99)
7

Makros in Scheme sind hygienisch: tmp im Makro kollidiert nicht mit der Variablen tmp des Aufrufers.

Continuations

call/cc gibt einem Programm „den Rest der Berechnung“ als Funktion:

(define (zeige x) (display x) (newline))
 
(zeige (+ 1 (call/cc (lambda (k) (+ 10 (k 5))))))
 
(define (finde-erste-negative liste)
  (call/cc
   (lambda (zurueck)
     (for-each (lambda (x) (when (< x 0) (zurueck x))) liste)
     #f)))
(zeige (finde-erste-negative '(3 5 -2 7 -9)))
(zeige (finde-erste-negative '(1 2 3)))
 
(define (produkt liste)
  (call/cc
   (lambda (abbruch)
     (let schleife ((l liste))
       (cond ((null? l) 1)
             ((zero? (car l)) (abbruch 0))
             (else (* (car l) (schleife (cdr l)))))))))
(zeige (produkt '(2 3 4)))
(zeige (produkt '(2 0 4 1000000)))

Ausgabe:

6
-2
#f
24
0

Merke

  • Funktionen sind Werte: lambda, map, fold, filter, any, every
  • Closures kapseln Zustand; Nachrichten an Funktionen ergeben einfache Objekte
  • syntax-rules erzeugt hygienische Makros
  • call/cc fängt die Fortsetzung ein: Basis für Ausnahmen, Generatoren und Koroutinen

Übungsaufgabe

Baue mit call/cc eine Funktion suche, die beim ersten Treffer abbricht.

Quiz zur Selbstkontrolle

Weiter im Kurs

Zurück: Strings, Vektoren, Hashtabellen und Records

Weiter: Ein-/Ausgabe, Fehlerbehandlung und Module

Alle Kapitel: Scheme im Überblick