2

Procedures

2.1.   Defining and Applying Procedures

2.1.1.   The Environmental Influence

(define (square z) (* z z))

(define (dist x y) (abs (- x y)))

(define num
   (- 1 (+ (square (sin 3)) (square (cos 3)))))

 

(define (close? a b) (<= (dist a b) _delta))

(define _delta 1e-20)

(define (small? z) (close? z 0))

2.1.2.   The Modularity Principle and Top-Down Design

; = volume of length len & radius rad capped pipe
(define (pipe-volume len rad)
   (+ (cylinder-volume len rad)
      (sphere-volume rad)))

; = volume of length len & radius rad cylinder
(define (cylinder-volume len rad)
   (* len (circle-area rad)))

(define four-thirds-pi (* (/ 4 3) pi))

(define pi (acos -1)) ; since (cos pi) = -1

; = volume of radius rad sphere
(define (sphere-volume rad)
   (* four-thirds-pi (cube rad)))

; = area of radius rad circle
(define (circle-area rad)
   (* pi (square rad)))

; = z^2
(define (square z) (* z z))

; = z^3
(define (cube z) (* z z z))

2.2.   Building Procedures Using Application

2.2.1.   Example: Coercions

; = symbol made from a vector of chars
(define (vector->symbol char-vector)
   (string->symbol
      (list->string (vector->list char-vector))))

; = char vector made from a symbol
(define (symbol->vector symbol)
   (list->vector
      (string->list
         (symbol->string symbol)))

; = # yards in m miles
(define (mile->yard m)
   (* 1760 m))   ; 1 mile = 1760 yards

; = # feet in y yards
(define (yard->foot y) (* 3 y))

; = #inches in f feet
(define (foot->inch f) (* 12 f))

; = # inches in m miles
(define (mile->inch m)
   (foot->inch (yard->foot (mile->yard m))))

2.2.2.   Example: Palindromes

; = #t, if string is a palindrome
(define (palindrome? string)
   (string-ci=? string (string-reverse string)))

; = reverse of string
(define (string-reverse string)
   (list->string (reverse (string->list string))))

2.3.   The Abstraction Principle

2.3.1.   Constructors

2.3.2.   Selectors

2.3.3.   Lists as Pairs

(define (cddadr x) (cdr (cdadr x)))

2.3.4.   Example: Association Lists as Records

; = record representing a student
(define (make-student name ssn gpa)
   (list (cons 'name name)
         (cons 'ssn ssn)
         (cons 'gpa gpa)))

; = name of student
(define (name student)
   (cdar student))

; = social security number of student
(define (ssn student)
   (cdadr student))

; = grade point average of student
(define (gpa student)
   (cdaddr student))

(define name cdar)
(define ssn cdadr)
(define gpa cdaddr)

(define picard (make-student "Picard" 998869999 3.75))

(define moe (make-student "Moe" 002869999 1.5))

(define spock (make-student "Spock" 905869999 3.9))

; = #t if student's gpa < 2.0
(define (probation? student)
   (< (gpa student) 2.0))

; = result of updating student's gpa to new-gpa
(define (update-gpa student new-gpa)
   (make-student
      (name student) (ssn student) new-gpa))

2.4.   Polymorphic Procedures

(define (id val) val)      ; the identity procedure

(define (always-0 val) 0)

(define (first val1 val2) val1)

(define (second val1 val2) val2)

(define (make-pair val) (cons val val))

2.4.1.   Equivalence Predicates

2.4.2.   The not and null? Predicates

(define (unfalse? val) (not (not val)))

2.4.3.   Recognition Predicates

2.4.4.   Example: Searching Association Lists

(define test1
   '(("Picard" . 92) ("Moe" . 34) ("Spock" . 99)))

(define test2
   '(("Picard" . 90) ("Moe" . 37) ("Spock" . 100)))

(define test3
   '(("Picard" . 89) ("Moe" . 36) ("Spock" . 99)))

(define tests
   (list (cons 'test1 test1)
         (cons 'test2 test2)
         (cons 'test3 test3)))

Graphs

(define string->digit-graph
   '(("zero" . 0) ("one" . 1) ("two" . 2)
    ("three" . 3) ("four" . 4) ("five" . 5)
    ("six" . 6) ("seven" . 7) ("eight" . 8)
    ("nine" . 9)))

; = coercion of string to corresponding digit
(define (string->digit string)
   (cdr (assoc string string->digit-graph)))

2.5.   Meta Procedures

; = average of numbers in the list nums
(define (average nums)
   (/ (apply + nums) (length nums)))

; = #t if names is sorted
(define (sorted? names) (apply string-ci<=? names))

; = average score of test
(define (test-avg test)
   (average (map cdr test)))

; = #t if for all v in vals (red? v) = #t
(define (all? pred? vals)
   (not (member? #f (map pred? vals))))

; = #t if some (pred? v) = #t for some v in vals
(define (some? pred? vals)
   (member? #t (map pred? vals)))

(define (member? val vals)
   (unfalse? (member val vals)))

; = #t if all members of list vals are characters
(define (char-list? vals)
   (all? char? vals))

; = #t if string contains a vowel
(define (contains-vowel? string)
   (some? vowel? (string->list string)))

Appendices

Appendix 2.1.   Mathematics in Scheme

Arithmetic

Comparing Characters and Strings

Divisibility

; = #t if m divides n
(define (divides? m n)
   (zero? (remainder m n)))

Congruence

; = #t if m is congruent to n mod k
(define (congruent? m n k)
   (divides? (- m n) k))

; = m + n mod k
(define (mod+ m n k) (modulo (+ m n) k))

; = m * n mod k
(define (mod* m n k) (modulo (* m n) k))

; = m - n mod k
(define (mod- m n k) (modulo (- m n) k))

; = m/n mod k
(define (mod/ m n k) (modulo (quotient m n) k))

; = time h hours after time t
(define (hours+ t h) (mod+ t h 24))

(define (bit+ b1 b2) (mod+ b1 b2 2))

Common Multiples and Divisors

Logs and Exponents

; = log y base x
(define (logt x y) (/ (log y) (log x)))

; = z^(1/n)
(define (nth-root z n) (expt z (/ n)))

Example

; = value of $p investment at rate r after n periods
(define (value p r n)
   (* p (expt (+ 1 r) n)))

Trigonometry

; = csc of z radians
(define (csc z) (/ (sin z)))

; = cot of z radians
(define (cot z) ???)   

; = sec of z radians
(define (sec z) ???)   

(define pi (acos -1))   ; since (cos pi) = -1

Appendix 2.2.    Sequences

Appending Sequences

; = result of adding val to end of vals
(define (cons-last val vals)
   (append vals (list val)))

Computing Lengths of Sequences

Extracting Subsequences

; = #t if val is in vals
(define (member? val vals)
   (unfalse? (member val vals)))

(define vowels
   '(#\a #\A #\e #\E #\i #\I #\o #\O #\u #\U))

(define punctuation '(#\. #\, #\; #\: #\! #\? #\-))

(define (vowel? char)
   (member? char vowels))

(define (punctuation? char)
   (member? char punctuation))

; = tail of vec beginning at val
(define (vector-member val vec)
   (list->vector (member val (vector->list vec))))

; = tail of vec beginning at position pos
(define (vector-tail vec pos)
   (list->vector (list-tail (vector->list vec) pos)))

Substrings

; = prefix of string ending at position pos - 1
(define (prefix string pos)
   (substring string 0 pos))

; = suffix of string beginning at position pos
(define (suffix string pos)
   (substring string pos (string-length string)))

; = #t if string2 is a prefix of string1
(define (prefix? string1 string2)
   (string=?
      string2
      (prefix string1 (string-length string2))))

; = #t if string2 is a suffix of string1
(define (suffix? string1 string2)
   (string=?
      string2
      (suffix
         string1
         (- (string-length string1)
            (string-length string2)))))

Sublists

; = sublist between positions start and (end - 1)
(define (sublist vals start end)
   (list-prefix (list-tail vals start)
                (- (- end 1) start)))

; = prefix of vals ending at position pos
(define (list-prefix vals pos)
   (reverse (list-tail (reverse vals) (- (length vals) (+ pos 1)))))

Other Applications of list-prefix

; = result of removing item at position k from vals
(define (remove vals k)
   (append (list-prefix vals (- k 1))
          (list-tail vals (+ k 1))))

; = result of inserting item at position pos in vals
(define (insert vals item pos) ???)

; = result of replacing member at
; position pos by item in vals
(define (replace vals item pos) ???)

Optional Parameters

; = average of all parameters
(define (avg . nums) (average nums))

; = #t if all parameters are relatively prime
(define (rel-prime? . ints) (= 1 (apply gcd ints)))

; = #t if all parameters ≠ #f
(define (and? . vals) (all? unfalse? vals))

; = #t if some parameters ≠ #f
(define (or? . vals) (some? unfalse? vals)))

(define (unfalse? val) (not (not val)))

; = #t if b is between a and c
(define (between? a b c)
   (or? (<= a b c) (<= c b a)))

; = #t if parameters are sorted
(define (sorted? . strings)
   (or? (apply string<? strings)
       (apply string<? (reverse strings))))