Skip to content

Instantly share code, notes, and snippets.

@sliminality
Created January 30, 2017 04:11
Show Gist options
  • Save sliminality/e25dce8753ac7e05c07cc64631076a10 to your computer and use it in GitHub Desktop.
Save sliminality/e25dce8753ac7e05c07cc64631076a10 to your computer and use it in GitHub Desktop.
w17 eecs 111 review 1

EECS 111 Winter 2017

These .rkt files from the review session are hosted online for convenient access, but you should really download the originals if you intend to study them in any depth. Comment boxes don't appear well in plain text.

Also see this website for review materials and other examples from last quarter.

;; Conditionals
(require 2htdp/image)
(require cs111/iterated)
;; boolean is one of
;; - true (#true, #t)
;; - false (#false, #f)
;; and : boolean, boolean, ... -> boolean
;; returns true if and only if all inputs are true
(check-expect (and #t #t) #t)
(check-expect (and #f #t) #f)
;; or : boolean, boolean, ... -> boolean
;; returns true if at least one input is true
(check-expect (or #f #t) #t)
(check-expect (or #f #f) #f)
;; not : boolean -> boolean
(check-expect (not #t) false)
(check-expect (not #false) #t)
;; Conditionals vs. functions: conditionals will "skip" branches
;; `or` only requires one argument to be true
(or (> 5 3) ; this is true
(string=? "happy" "birthday")) ; so we never evaluate this
;; Consider this (nonsensical) case, where we skip an expensive computation
;; because we don't need to know the answer
(or (> 5 3)
;; the next line never gets called
(iterated-overlay (lambda (n) (circle n "solid" "red"))
100000000000000000000))
;; Technically this should throw an error because `iterated-overlay`
;; returns an image, and `or` takes booleans only
;; But we never throw the error if we never run the problematic code
;; Alternatively, suppose the first condition is #false, then we
;; have to check the next one to see if it's true...
;; This time we DO throw the error
; (or (= 5 3) ; 5 =/= 3, so this is #false
; (iterated-overlay (lambda (n) (circle n "solid" "red"))
; 100000000000000000000))
; ;; now we DO call the next line...
;; if : boolean, X, Y -> X or Y
; (if <Predicate> ; "predicate" = "boolean, or expression that simplifies to a boolean"
; <TrueCase>
; <FalseCase>)
;; If <Predicate> is true, we
;; skip the <FalseCase> branch entirely
(if (> 2 1)
"it was true"
(5)) ; this should throw an error (why?), but we never run it
;; checks-value : any -> string
(define (checks-value x)
(if (string? x)
(if (string=? "hello")
"it was a string that was hello"
"it was a string that wasn't hello")
(if (number? x)
(if (= x 2)
"it was 2"
"it was a number that wasn't 2")
"it was not a string or number")))
;; Notice we are COMPOSING `if` statements here
; (if <Predicate>
; <TrueCase> ; this can be another `if` statement
; <FalseCase> ; this can also be another `if` statement
;; USE THE STEPPER ON SOME EXAMPLES
;; IT'S CONFUSING TO JUST TRY TO READ IT
; (cond
; [<Predicate> <ReturnValue>]
; [<Predicate> <ReturnValue>]
; [<Predicate> <ReturnValue>]
; ...
; [else <Catch-AllValue>])
;; Some stuff is really annoying to write with `if`
; ;; check-type : any -> string
; (define check-type
; (lambda (x)
; (if (string? x)
; "string"
; ;; Notice we're nesting another `if` in the `else` case
; (if (number? x)
; "number"
; (if (boolean? x)
; "boolean"
; (if (image? x)
; "image"
; ; ... this could go on forever...
; ; ...
; "type unrecognized"))))))
;; How about using `cond`?
;; check-type : any -> string
(define check-type
(lambda (x)
(cond
[(string? x) "string"]
[(number? x) "number"]
[(boolean? x) "boolean"]
[(image? x) "image"]
;; ...
[else "type unrecognized"])))
;; Lambda
;; (lambda (...) ...) gives you an anonymous function
;; f(x, y) = x^2 + 1 + y
;; ~~~~~~~~~~~~~~~~~~~~
;; aka this part
; ;; f (x, y) = x^2 + 1 + y
; (define f (lambda (x y) (+ (sqr x) 1 y)))
;; (x, y) = x^2 + 1 + y (note no f)
(lambda (x y) (+ (sqr x) 1 y))
;; Anonymous functions suck to evaluate, so we give them names
;; ((x, y) = x^2 + 1 + y)(5, 6)
((lambda (x y) (+ (sqr x) 1 y))
5 6)
;; f(x, y) =
;; x^2 + 1 + y
(define f
(lambda (x y) (+ (sqr x) 1 y)))
;; f(5, 6)
(f 5 6)
;; 1. Substitute the function name for the anonymous body
;; f(5, 6) = x^2 + 1 + y
((lambda (x y) (+ (sqr x) 1 y))
5 6)
;; 2. Substitute argument values in the function bodu
;; (5)^2 + 1 + (6)
(+ (sqr 5) 1 6)
;; 3. Simplify from inside out, left to right
;; (5)^2 + 1 + (6)
;; => 25 + 1 + (6)
;; => 32.
(+ 25 1 6)
32
;; When you have one value left, return it.
;; You can also use anonymous functions whenever you're not going to use
;; a function more than once. You don't HAVE to give it a name. It's not
;; that huge of an inconvenience if you're only using it once.
(iterated-overlay
(lambda (n) (circle (* n 20) "solid" "red")) ; prob not gonna use this again
10)
;; equivalently,
(define helper (lambda (n) (circle (* n 20) "solid" "red")))
;; or (define (helper n) (circle (* n 20) "solid" "red"))
(iterated-overlay helper 10)
;; Structs
;; Define a struct
; (define-struct <StructName>
; [<Field1> <Field2> ... <FieldN>])
;; A contact is a struct: (make-contact string number)
(define-struct contact
[name age])
;; 1. Make a new struct
; (make-<StructName>
; <Field1Value> <Field2Value> ... <FieldNValue>)
(make-contact "Sara Sood" 25)
(define sara-contact (make-contact "Sara Sood" 25))
;; 2. Check if something is an instance of the struct
; (<StructName>? <anything>)
(contact? sara-contact)
(contact? 10)
;; 3. Access fields on a struct
; (<StructName>-<FieldName> <Struct>)
(contact-name sara-contact)
(contact-age sara-contact)
; ;; Can't do stuff like
; (contact-name "Bob") ; "Bob" is a string, not a contact
; (contact-birthday sara-contact) ; birthday is not a field
;; Primitive Types & Signatures
(require 2htdp/image)
(require cs111/iterated)
;; Type signatures dictate how to use a function
;; circle : number, string, string -> image
(circle 20 "solid" "red")
;; Rule 1. Parens are used exclusively to call functions
; (<Chunk> ...)
; (<Chunk> <a> <b> <c> ...)
;
; <Chunk> must be either a function name, or a lambda.
;; Recall that (define <Name> <Value>) means that any time we see
;; <Name>, we plug in <Value>
; (define HEIGHT 400)
;
; (+ HEIGHT 1) ; by substitution, becomes (+ 400 1)
;; Sussman form gets converted to lambda form
;; Function names are substituted just like variables
;; pythagorean : number, number -> number
;; a^2 + b^2 = c^2
;; => sqrt(a^2 + b^2)
(define pythagorean
(lambda (a b)
(sqrt (+ (sqr a) (sqr b)))))
(pythagorean 3 4) ; by substitution, becomes (lambda (a b) (sqrt (+ (sqr a) (sqr b))))
;; Rule 2. Expand everything, performing substitution if needed, and then
;; simplify from inside out
;; Use the Stepper, Luke
(pythagorean 3 4)
;; Structs
;; Define a struct
; (define-struct <StructName>
; [<Field1> <Field2> ... <FieldN>])
;; A contact is a struct: (make-contact string number)
(define-struct contact
[name age])
;; 1. Make a new struct
; (make-<StructName>
; <Field1Value> <Field2Value> ... <FieldNValue>)
(make-contact "Sara Sood" 25)
(define sara-contact (make-contact "Sara Sood" 25))
;; 2. Check if something is an instance of the struct
; (<StructName>? <anything>)
(contact? sara-contact)
(contact? 10)
;; 3. Access fields on a struct
; (<StructName>-<FieldName> <Struct>)
(contact-name sara-contact)
(contact-age sara-contact)
; ;; Can't do stuff like
; (contact-name "Bob") ; "Bob" is a string, not a contact
; (contact-birthday sara-contact) ; birthday is not a field
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment