;; 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 ()))) ; für Benutzung von n-th: (require "listoperations.rkt") ; Eine Funktionsanwendung besteht aus ; - einem Funktionsnamen (string) ; - einer Liste von Argumenten (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 eine Summe? (: sum? (any -> boolean)) (define sum? (lambda (x) (if (fun-app? x) (string=? (fun-app-name x) "+") #f))) ; Ist das Argument ein Produkt? (: 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 (x y) (and (variable? x) (variable? y) (string=? x y)))) ; spezielle Konstruktoren: ; Konstruiere aus zwei Teilfunktionsausdrücken die Summe dieser beiden: (: sum (fun-exp fun-exp -> fun-exp)) #;(define sum (lambda (f1 f2) (make-fun-app "+" (list f1 f2)))) ; mit Vereinfachungsregeln: (define sum (lambda (f1 f2) (cond ((and (constant? f1) (constant? f2)) (+ f1 f2)) ((constant? f1) (if (= f1 0) f2 (make-fun-app "+" (list f1 f2)))) ((constant? f2) (if (= f2 0) f1 (make-fun-app "+" (list f1 f2)))) (else (make-fun-app "+" (list f1 f2)))))) ; Konstruiere aus zwei Teilfunktionsausdrücken das Produkt dieser beiden: (: prod (fun-exp fun-exp -> fun-exp)) (define prod (lambda (f1 f2) (cond ((and (constant? f1) (constant? f2)) (* f1 f2)) ((constant? f1) (cond ((= f1 0) 0) ((= f1 1) f2) (else (make-fun-app "*" (list f1 f2))))) ((constant? f2) (cond ((= f2 0) 0) ((= f2 1) f1) (else (make-fun-app "*" (list f1 f2))))) (else (make-fun-app "*" (list f1 f2)))))) ; Beispielausdruck: (: axb fun-exp) (define axb (sum (prod "a" "x") "b")) ; Selektoren: ; Berechne den ersten Operanden einer Funktionsanwendung: (: operand1 (fun-app -> fun-exp)) (define operand1 (lambda (f) (n-th (fun-app-args f) 0))) ; Berechne den zweiten Operanden einer Funktionsanwendung: (: operand2 (fun-app -> fun-exp)) (define operand2 (lambda (f) (n-th (fun-app-args f) 1))) ; Berechne die erste Ableitung eines Funktionsausdrucks ; nach einer Variablen: (: derive (fun-exp string -> fun-exp)) (check-expect (derive 42 "x") 0) (check-expect (derive "x" "x") 1) (check-expect (derive "a" "x") 0) (check-expect (derive (sum "x" 99) "x") 1) (check-expect (derive (prod "a" "x") "x") "a") (check-expect (derive axb "x") "a") #;(define derive (lambda (f x) (cond ((constant? f) ...) ((variable? f) ...) ((sum? f) ...) ((prod? f) ...)))) (define derive (lambda (f x) (cond ((constant? f) 0) ((variable? f) (if (equal-variable? f x) 1 0)) ((sum? f) (sum (derive (operand1 f) x) (derive (operand2 f) x))) ((prod? f) (sum (prod (operand1 f) (derive (operand2 f) x)) (prod (operand2 f) (derive (operand1 f) x)))))))