Skip to content
GitLab
Menu
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
CSE 341 22sp
CSE 341 22sp public
Commits
7f50e02f
Commit
7f50e02f
authored
Apr 25, 2022
by
James R. Wilcox
Browse files
lecture code for today
parent
8d75a1b7
Changes
3
Hide whitespace changes
Inline
Sidebyside
lecture/L13/demo.trefoil
0 → 100644
View file @
7f50e02f
(+ 1 2)
(define x (+ 1 2))
(define y (+ x 1))
(define (f x) (+ x 1))
(f y)
(define (pow b e)
(if (= e 0)
1
(* b (pow b ( e 1)))))
(pow 2 3)
(pow 10 7)
(define (countdown n)
(if (= n 0)
nil
(cons n (countdown ( n 1)))))
(countdown 10)
(define (sum l)
(if (nil? l)
0
(+ (car l) (sum (cdr l)))))
(sum (countdown 10))
(struct myrecord name present)
(define r (myrecord 'james true))
(myrecordname r)
(myrecordpresent r)
(myrecord? r)
(myrecord? (cons r 17))
(struct cheese)
(struct custom msg)
(define p1 (cheese))
(define p2 (custom 'olives))
(define (or x y) ;; warning! does not shortcircuit
(if x true y))
(define (pizza? p)
(or (cheese? p) (custom? p)))
(pizza? p1)
(pizza? p2)
(pizza? 17)
(pizza? (cons p1 p2))
; nil is almost like (struct nil) plus (define nil (nil))
; cons is almost like (struct cons car cdr) plus (define (car x) (conscar x)) (define (cdr x) (conscdr x))
(struct constant num)
(struct plus e1 e2)
(define (eval e)
(if (constant? e)
(constantnum e)
(if (plus? e)
(+ (eval (pluse1 e))
(eval (pluse2 e)))
'error)))
(eval (plus (constant 1) (constant 2)))
(define (eval e)
(cond
((constant? e) (constantnum e))
((plus? e)
(+ (eval (pluse1 e))
(eval (pluse2 e))))))
(eval (plus (constant 1) (constant 2)))
; k is anything
; l is a list of pairs
; returns the first pair of l whose first component is equal to k
; or nil if no such pair
; note: returns the *pair* on success  you have to call cdr to get the value
; (why did james do it this way?)
(define (assoc k l)
(if (nil? l)
nil
(if (= k (car (car l)))
(car l)
(assoc k (cdr l)))))
(struct variable symbol)
(define (eval dynenv e)
(cond
((variable? e) (cdr (assoc (variablesymbol e) dynenv)))
((constant? e) (constantnum e))
((plus? e)
(+ (eval dynenv (pluse1 e))
(eval dynenv (pluse2 e))))))
(eval nil (constant 3))
(eval nil (plus (constant 1) (constant 2)))
(eval (cons (cons 'x 17) nil)
(plus (constant 1) (variable 'x)))
lecture/L13/demolive.trefoil
0 → 100644
View file @
7f50e02f
; it's alive
(+ 1 2)
(define x (+ 1 2))
(define y (+ x 1))
(define (f x) (+ x 1))
(f y)
(define (pow b e)
(if (= e 0)
1
(* b (pow b ( e 1)))))
(pow 2 3)
(pow 10 7)
(define (countdown n)
(if (= n 0)
nil
(cons n (countdown ( n 1)))))
(countdown 10)
(define (sum l)
(if (nil? l)
0
(+ (car l) (sum (cdr l)))))
(sum (countdown 10))
;;; remember "Ocaml records as structs"
;;; type myrecord = { name: string; present: bool }
(struct myrecord name present)
; generates several things
;  constructor: like a function with the same name as the struct
;  builds values of tye myrecord type
;  accessor functions for each field (james calls these projections on accident; just ignore him)
;  each function gets the corresponding field
;  look later for "predicates" to see the last thing that gets generated
(define r (myrecord 17 true))
(myrecordname r)
(myrecordpresent r)
;;; remember "Ocaml variants as structs"
;;; type pizza = Cheese  Custom of string
; rule is: for each constructor of the OCaml variant type, introduce a trefoil struct
(struct cheese)
(struct custom instructions)
(define p1 (cheese))
(define p2 (custom 'onlyolives)) ; "fake strings" aka symbols
; Symbols:
; must start with an apostrophe
; have no spaces
; other than that, they're pretty much strings
; you can't do anything to them except (= ... ) comparison
;;; in OCaml:
; p has type pizza
; match p with
;  Cheese > "cheese"
;  Custom msg > "a custom pizza: " ^ msg
; the last thing that a struct declaration generates
;  a "predicate function", whose name is the name of the struct plus "?"
;  returns true if its argument was built with the constructor of this struct
; and false otherwise
p1
(cheese? p1)
p2
(cheese? p2)
(cheese? 17)
(custom? p1)
(custom? p2)
;; similarities to nil/cons
; builtin value nil is almost like
; (struct nil)
; (define l (nil)) ;; would be an error if we didn't have builtin nil
;
; ; could work around that with
; ; (define nil (nil))
; builtin cons constructor is almost like
; (struct cons car cdr)
; (define newpair (cons 1 2)) ; if we deleted builtin cons, this would build values of our new struct
;
; ; would require slightly different names for accessors
; (conscar newpair)
; (conscdr newpair)
; could work around that
; (define (car x) (conscar x))
; (define (cdr x) (conscdr x))
;; OCaml:
;; type expr = Constant of int  Plus of expr * expr
;;
;; let example = Plus(Constant(1), Constant(2))
;;
;; let rec eval (e: expr) =
;; match e with
;;  Constant(n) > n
;;  Plus(e1, e2) > eval e1 + eval e2
; an expression is either a constant or a plus
(struct constant num)
(struct plus e1 e2)
(define example
(plus
(constant 1)
(constant 2)))
; given an expression, evaluate it to its value
(define (eval e)
(if (constant? e)
(constantnum e)
(if (plus? e)
(+ (eval (pluse1 e))
(eval (pluse2 e)))
'error)))
(eval example)
; syntax of cond:
;
; (cond (p1 b1) ... (pn bn))
;
; (n can be zero)
; all of the the p_i and b_i are expressions
; semantics of cond:
;
; evaluate p1 to a value v1. if v1 is false, "keep going"
; otherwise, evaluate b1 and return that as the value for the whole cond
; to keep going, evaluate p2 and so on
;
; if you get through all the p_i and none are truthy, signal an error
;; old version
; (define (eval e)
; (if (constant? e)
; (constantnum e)
; (if (plus? e)
; (+ (eval (pluse1 e))
; (eval (pluse2 e)))
; 'error)))
;; new version with cond
(define (eval e)
(cond
((constant? e) (constantnum e))
((plus? e)
(+ (eval (pluse1 e))
(eval (pluse2 e))))
(true 'error)))
(eval example)
\ No newline at end of file
lecture/L13/lec13.ml
0 → 100644
View file @
7f50e02f
(* in Java, we had a superclass for expressions, and then one subclass per kind of expression *)
(* in OCaml, we have one giant variant type for expressions, with one constructor per kind *)
type
expr
=

Constant
of
int

Plus
of
expr
*
expr
(* add a new kind of expression: add a constructor to the expr type *)

Minus
of
expr
*
expr

Variable
of
string
(* in Java, used hash maps and lots of copying to implement dynamic environment *)
(* in OCaml, we will use an "association list":
 list of pairs
 each pair's first element is a "key"
 second element is a "value"
lookup elements in the list by recursion, searching for a key.
add elements to the list with cons
*)
type
association_list
=
(
string
*
expr
)
list
type
dynamic_environment
=
association_list
let
rec
lookup
((
assoc_list
:
association_list
)
,
(
key
:
string
))
:
expr
=
match
assoc_list
with

[]
>
failwith
"lookup failed to find key"

(
key'
,
v
)
::
list
>
if
key'
=
key
then
v
else
lookup
(
list
,
key
)
let
rec
eval
(
dynenv
,
e
)
=
(* in Java, we would do instanceof checks to figure out what kind of expression *)
(* in OCaml, we use pattern matching *)
match
e
with

Constant
(
n
)
>
n

Plus
(
e1
,
e2
)
>
eval
(
dynenv
,
e1
)
+
eval
(
dynenv
,
e2
)

Minus
(
e1
,
e2
)
>
eval
(
dynenv
,
e1
)

eval
(
dynenv
,
e2
)

Variable
(
x
)
>
(* look up x in the dynamic environment. *)
lookup
(
dynenv
,
x
)
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment