;; The first three lines of this file were inserted by DrRacket. They record metadata ;; about the language level of this file in a form that our tools can easily process. #reader(lib "htdp-beginner-reader.ss" "lang")((modname lect02c) (read-case-sensitive #t) (teachpacks ((lib "universe.ss" "teachpack" "2htdp") (lib "image.ss" "teachpack" "2htdp"))) (htdp-settings #(#t constructor repeating-decimal #f #t none #f ((lib "universe.ss" "teachpack" "2htdp") (lib "image.ss" "teachpack" "2htdp"))))) ;;;;; lect02c.rkt ; symbols: ; examples: 'jack 'queen 'red 'yellow 'green 'amy 'george ... ; Can often be used as an enumerated type, ; or like a string that I'll never want to call substring/string-ref/string-concat etc. ; The *only* useful function involving symbols: symbol=? symbol? ; ; symbol=? : symbol, symbol -> boolean ; symbol? : ANY -> boolean ; integer? : ANY -> boolean ;;; Review: (define (root1 a b c) (/ (+ (- b) (sqrt (- (* b b) (* 4 a c)))) (* 2 a))) ; parameter (a,b,c) is a variable-name ; argument (4,7,3) is a *value* that get passed in to a function ;;; Review: #| The Law of Scheme: Given an expression, evaluate it to get a value. An Expression is one of: And to evaluate it, you: 1. value 23, "hi", false, #\A, ... - just use that value (duh!) 2. identifier x, char->integer - look up reulst of previous `define` 3. function-application: - Eval exrp0..exprn (expr0 expr1 ... exprn) to get val0, val1, ..., valn (val0 had better be a func!) e.g. (+ 2 (* 3 4) 5); (a) if val0 is a built-in primitive, expr1 is `7` call that with val1...valn, expr2 is `(* 3 4)` and that's your answer. expr3 is `5` (b) if val0 is a user-defined function, expr0 is the abstract func `addition` take the body of the func, subst the params with val1,...,valn Then evaluate *that* for your answer. 4. Special Forms (with their own syntax, and rules-of-evaluation): define -- don't eval the first "argument" and,or -- short-circuit if,cond -- short-circuit: only eval the 2nd *or* 3rd arg, not both define-struct -- stay tuned... |# ;;; Review: ;;; If you have a union-type ;;; ("A Blargh is either: ;;; - a char, *or* ;;; - an int, *or* ;;; - a boolean"), ;;; your code that processes a Blargh will naturally start with ???? ;;; Aside: the syntax of `cond`: #;(cond [q1 a1] [q2 a2] ... [qn an]) ;;; (Think q,a for question,answer.) ;;; Each of q1..qn is any expression (presumably evals to a boolean), ;;; or it's the word `else` which is equivalent to `#t`. ;;; Each of a1...an are any expression. ;;; ;;; The semantics of cond: ;;; Evaluate q1; if it's true then return result of eval'ing a1; otherwise ;;; Evaluate q2; if it's true then return result of eval'ing a2; otherwise ;;; ... ;;; Evaluate qn; if it's true then return result of eval'ing an; otherwise ;;; raise an error (in student-languages -- full lang returns (void)). ;;; An example (two, really): ;;; test cases (write 'em first!) (check-expect (crank-value 5) 0) (check-expect (crank-value 'queen) 2) ; crank-value : c-rank -> int ; compute the bridge-playing value for a given c-rank. (define (crank-value a-cr) (cond [(integer? a-cr) 0] [(symbol? a-cr) (cond [(symbol=? a-cr 'jack) 1] [(symbol=? a-cr 'queen) 2] [(symbol=? a-cr 'king) 3] [(symbol=? a-cr 'ace) 4])])) ;;;;;;; Exercise, to check your review/understanding: ;; Write a function to compute income tax, according to: ;; income [0,$10,000) -- no tax ;; income [$10,000, $25,000) -- 10% of the amount above $10,000 ;; income [$25,000,+infinity) -- 25% of the amount above $25,000 plus $1500 (check-expect (income 0) 0) (check-expect (income 3000) 0) (check-expect (income 10000) 0) (check-expect (income 15000) 500) (check-expect (income 24999.99) 1499.999) (check-expect (income 25000) 1500) (define (income x) (cond [(< x 10000) 0] [(and (<= 10000 x) (< x 25000)) (* 0.10 (- x 10000))] [(<= 25000 x) (+ (* 0.25 (- x 25000)) 1500)])) ;;; Since we're handling data that can be integer OR character, ;;; we'll use "cond", which is like if-else-if: #;(define (func-for-c-ranks a-cr) (cond [(integer? a-cr) ...] [(character? a-cr) ...])) (check-expect (crank->string 5) "5") (check-expect (crank->string 10) "10") (check-expect (crank->string 'queen) "Q") ; crank->string : c-rank -> string ; (define (crank->string a-cr) (cond [(integer? a-cr) (number->string a-cr)] [(symbol? a-cr) (string (char-upcase (string-ref (symbol->string a-cr) 0)))])) ;;;;;;;;;;;;;;;;;;;;;;;;;;; Hour 3 ;;;;;;;;;;;;;;;;;;;;; ; Exercise: write a function that takes in c-rank, and returns ...? ; Let's see how much we can write w/o even knowing WTF ("what the function?") ; A c-rank is either: ; - an integer (2..10) ; or - a symbol ('jack, 'queen, 'king, 'ace) ; Btw, we can write: ; crank? ANY -> boolean ; (define (crank? any) (or (and (integer? any) (<= 2 any 10)) (symbol? any))) ; ; The design recipe: ; http://htdp.org/2003-09-26/Book/curriculum-Z-H-7.html#node_sec_4.4 ; --- per (abstract) data type: ; - data def'n ; - examples of data ; - template (case analysis) ; --- per function: ; - contract, purpose, header ; - test-cases (check-expect) ; - complete function-body ; - case analysis (cond-questions, 1 per data variant) ; - answer for each cases ; - run the tests (trivial) ;;;;;;;;;;;;;;;;; Next stage: define-struct (product type) ; ; My data definition: ; (define-struct card (rank suit)) ; rank : card-rank ; suit : symbol ; Examples of the data: ; (make-card 4 'spades) (make-card 'queen 'hearts) ; When I define-struct, racket creates four functions for me: ; make-card -- constructor ; card-rank -- accessor ; card-suit -- accessor ; card? -- predicate ; have-a-heart : c-rank -> card ; Return a card of the given rank, in hearts.