;; Die ersten drei Zeilen dieser Datei wurden von DrRacket eingefügt. Sie enthalten Metadaten ;; über die Sprachebene dieser Datei in einer Form, die DrRacket verarbeiten kann. #reader(lib "DMdA-vanilla-reader.ss" "deinprogramm")((modname symbdiff) (read-case-sensitive #f) (teachpacks ()) (deinprogramm-settings #(#f write repeating-decimal #f #t none explicit #f ()))) ; Eine Funktionsanwendung besteht aus ; - einem Funktionsnamen (string) ; - einer Argumentliste (define-record-procedures fun-app make-fun-app fun-app? (fun-app-name fun-app-args)) ; Ein Funktionsausdruck ist eins der folgenden: ; - eine Konstante (number) ; - eine Variable (string) ; - eine Funktionsanwendung (fun-app) (define fun-exp (signature (mixed number string fun-app))) (: make-fun-app (string (list-of fun-exp) -> fun-app)) (: fun-app? (any -> boolean)) (: fun-app-name (fun-app -> string)) (: fun-app-args (fun-app -> (list-of fun-exp))) ; Ist das Argument eine Konstante? (: constant? (any -> boolean)) (define constant? (lambda (x) (number? x))) ; Ist das Argument eine Variable? (: variable? (any -> boolean)) (define variable? (lambda (x) (string? x))) ; Ist das Argument die Summe zweier Funktionsausdrücke? (: sum? (any -> boolean)) (define sum? (lambda (x) (if (fun-app? x) (string=? (fun-app-name x) "+") #f))) ; Ist das Argument das Produkt zweier Funktionsausdrücke? (: prod? (any -> boolean)) (define prod? (lambda (x) (if (fun-app? x) (string=? (fun-app-name x) "*") #f))) ; Sind die beiden Argumente identische Variablen? (: equal-variable? (any any -> boolean)) (define equal-variable? (lambda (v1 v2) (and (variable? v1) (variable? v2) (string=? v1 v2)))) ; Konstruiere aus zwei Funktionsausdrücken deren Summe (: sum (fun-exp fun-exp -> fun-exp)) #;(define sum (lambda (f1 f2) (make-fun-app "+" (list f1 f2)))) (define sum (lambda (f1 f2) (cond ((and (constant? f1) (constant? f2)) (+ f1 f2)) ((and (constant? f1) (= f1 0)) f2) ((and (constant? f2) (= f2 0)) f1) (else (make-fun-app "+" (list f1 f2)))))) ; Konstruiere aus zwei Funktionsausdrücken deren Produkt (: prod (fun-exp fun-exp -> fun-exp)) #;(define prod (lambda (f1 f2) (make-fun-app "*" (list f1 f2)))) (define prod (lambda (f1 f2) (cond ((and (constant? f1) (constant? f2)) (* f1 f2)) ((and (constant? f1) (= f1 0)) 0) ((and (constant? f2) (= f2 0)) 0) ((and (constant? f1) (= f1 1)) f2) ((and (constant? f2) (= f2 1)) f1) (else (make-fun-app "*" (list f1 f2)))))) ; ax+b (define axb (sum (prod "a" "x") "b")) ; Selektor: berechne den ersten Operanden einer Funktionsanwendung (: operand1 (fun-app -> fun-exp)) (define operand1 (lambda (f) (n-th (fun-app-args f) 0))) ; Selektor: berechne den zweiten Operanden einer Funktionsanwendung (: operand2 (fun-app -> fun-exp)) (define operand2 (lambda (f) (n-th (fun-app-args f) 1))) (define n-th (lambda (xs n) (cond ((empty? xs) (violation "n-th: list too short")) ((cons? xs) (if (= n 0) (first xs) (n-th (rest xs) (- n 1))))))) ; Berechne symbolisch die erste Ableitung einer Funktion nach einer Variable (: derive (fun-exp string -> fun-exp)) (check-expect (derive 42 "x") 0) (check-expect (derive "x" "x") 1) (check-expect (derive "y" "x") 0) (check-expect (derive (sum "x" 2) "x") 1) (check-expect (derive (prod "x" "y") "x") "y") (check-expect (derive axb "x") "a") (define derive (lambda (f v) (cond ((constant? f) 0) ((variable? f) (if (equal-variable? f v) 1 0)) ((sum? f) (sum (derive (operand1 f) v) (derive (operand2 f) v))) ((prod? f) (sum (prod (operand1 f) (derive (operand2 f) v)) (prod (operand2 f) (derive (operand1 f) v)))) )))