Commit fe09b1c0 authored by James R. Wilcox's avatar James R. Wilcox
Browse files

lec08 code

parent 0b67026b
......@@ -6,4 +6,17 @@ type myrecord = {
}
let r = { name = "james"; height = 75}
let who = r.name
\ No newline at end of file
let who = r.name
let s = ("james", 75)
let who2 = fst s
(* both records and tuples are "each of" types. ("all of")
a value has "each of" its components
r has each of {name, height}
s has each of {fst, snd}
*)
; bonus material!!!!!!!!!
;
; goal: define "a > b" operator without having to add it to the language
;
; the language has recursion, arithmetic, and = on integers
;
; first idea: suffices to implement the "n > 0" operator, since "a > b"
; is equivalent to (a - b) > 0.
;
; second idea: we can "search downwards for zero" by repeatedly subtracting 1 from n.
; if n is positive, we will eventually find zero.
; if n is negative, this will loop forever.
;
; third idea: on the other hand, with a negative number, we could "search upwards"
; by repeatedly adding 1 to n.
; if n is negative, we will eventually find zero.
; if n is positive, this will loop forever.
; fourth idea: do both searches "at the same time". one of them is guaranteed to terminate.
; and whichever one terminates tells you whether the original n was positive or negative
; :)
; precondition: either down is >= 0 or up is <= 0
; repeatedly decrements down and increments up
; if down hits zero, returns true.
; if up hits zero, returns false.
; if they hit zero at the same time, returns true.
(define (downup-search down up)
(if (= down 0)
true
(if (= up 0)
false
(downup-search (- down 1) (+ up 1)))))
; a function whose name is ">=0" just for fun
(define (>=0 n)
(downup-search n n))
(test (>=0 0))
(test (>=0 -0))
(test (>=0 1))
(test (>=0 100))
(define (not b)
(if b false true))
(test (not (>=0 -1)))
(test (not (>=0 -100)))
; warning: not short-circuiting!
(define (and b1 b2)
(if b1 b2 false))
(define (>0 n)
(and (>=0 n) (not (= n 0))))
(test (not (>0 0)))
(test (not (>0 -0)))
(test (>0 1))
(test (>0 100))
(test (not (>0 -1)))
(test (not (>0 -100)))
(define (> a b)
(>0 (- a b)))
(test (> 10 3))
(test (not (> -1 5)))
(test true)
(test false)
(test 0)
(test 1)
(define x true)
(define y false)
(define z 0)
(define w 1)
(if x 17 42)
(if y 17 42)
(if z 17 42)
(if w 17 42)
(test x)
(test y)
(test z)
(test w)
; test bindings
(test true)
(test false) ; a test fails if it does not return true
(test 17) ; a test fails if it does not return true
(define a 5)
a
(test (= a 5))
(define x true)
(define y false)
(define z 0)
(define w 1)
(test x) ; x is "truthy"
(test y) ; y is "falsey"
(test z) ; z is "falsey" from a test binding perspective
(test w) ; w is "falsey" from a test binding perspective
;; different in if expressions!!!
(if x 17 42) ; x is "truthy"
(if y 17 42) ; y is "falsey"
(if z 17 42) ; z is "truthy" from a if expression perspective
(if w 17 42) ; w is "truthy" from a if expression perspective
; why is this useful in if expression
; it would be fun to implement n > 0 as a function :)
; return n - 1 if n > 0, otherwise return "None"
; in ocaml: we would return an "int option"
(define (f n)
(if (= n 0)
; #f ; unbound variable "#f" ; oops racket brain
false
(- n 1)))
(f 0)
(f 1)
; (define (g n)
; (let ((y (f n)))
; (if y
; ; "Some" case
; ... do something with y now that we know it's an integer
; ; "None" case
; ... y is false, do some kind of error recovery)))
; functions and the dynamic environment
; dynamic environment: empty
(define x 1)
; dynamic environment: x -> 1
(define (f n) ; every time a function is defined, save the current dynamic environment
(+ n x))
; dynamic environment: x -> 1, f -> (function definition,
; the defining environment sneakily modified with
; f -> this pair)
;
;; or, better put: f -> (function definition, this whole environment)
(f 0) ; call a function
; 0. look up f in the current dynamic environment
; - get the function definition and the defining environment
; 1. evaluate the arguments in the current dynamic environment
; 2. evaluate the body of the definition of f in a new (temporary!) dynamic environment
; - start with the defining environment (lexical scope!!)
; - extended by argument name -> argument value for all arguments
; 3. the value that the body evaluates to is the return value of the function
;
(f 17)
(define x 2)
x
(f 0) ; 1!!
(f 17)
; dynamic scope:
; - evaluate the function body in the environment of the caller
; lexical scope (static scope):
; - evaluate the function body in the environment from when it was defined
; - requires saving the old dynamic environment!!
; what about recursion?
; imagine dynamic environment is empty at this point
(define (pow base exp)
(if (= exp 0)
1
(* base (pow base (- exp 1)))))
(pow 2 3)
; evaluate:
;(if (= exp 0)
; 1
; (* base (pow base (- exp 1))))
; in an environment
; base -> 2, exp -> 3
;;
; why would OCaml not just make all functions recursive?
;;
; (define foo 17)
;
; (define (foo x)
; (+ x foo)) ;; no way to refer to the variable foo here,
; ;; because foo is bound to the function foo
;
; (foo 10)
(* variants *)
(* "one of" type
a value of a variant has "one of" its component *)
type my_variant =
| Name of string
| Height of int
let a = Name "james" (* choose string/Name *)
let b = Height 75 (* choose int/Height *)
(* list that has strings and ints!!! *)
let l: my_variant list = [a; b]
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment