(* CS:4420 Artificial Intelligence Spring 2019 The University of Iowa Instructor: Cesare Tinelli *) (* OCaml examples seen in class *) (* Immutable records *) type employeeType = { id : int ; name : string ; age : int ; salary : float ; dept : char } let e = { id = 1098; name = "Joe Bull"; age = 22; salary = 3400.4; dept = 'S' } ;; e.name ;; e.dept ;; let { id = i; name = n; _ } = e (* builds e1 from e *) let e1 = { e with age = 40; dept = 'A' } ;; (* e is unchanged *) e ;; (* Mutable record types *) type mut_rec = { mutable x : int ; y : int } let r = { x = 5; y = 3 } ;; (* mutable fields can be assigned a new value *) r.x <- 10 ;; r ;; (* immutable fields cannot *) r.y <- 110 ;; type linkedList = { value : int ; mutable next : linkedList } (* pipe operator |> *) (* convenient to pipe the result of one function into another *) let f x = x + 1 let d x = x + x ;; f 1 |> d |> f ;; (* same result as the following *) f (d (f 1)) ;; (* |> Can be used for the last argument of a multi-argument function *) let g x y = y ^ x ;; "a" |> g "b" |> g "c" ;; let ins a l = a :: l ;; [] |> ins 1 |> ins 2 ;; (* Option Types *) type 'a option = None | Some of 'a let o1 = Some 0.4 let o2 = Some "aaa" let o3 = None let l = [] let f x = match x with | Some _ -> "I got something" | None -> "I got nothing" ;; f (Some 5) ;; f None ;; let g (x: int option) = match x with | Some n -> "I got " ^ string_of_int n | None -> "I got nothing" ;; g (Some 5) ;; (* Option type are convenient for functions that are not defined for all inputs *) let al = [("a", 3); ("c", 78); ("baf", 666); ("b", 111)] let rec find x al = match al with | [] -> failwith "key not found" | (k,v) :: t when x = k -> v | _ :: t -> find x t let rec findOpt x al = match al with | [] -> None | (k,v) :: t when x = k -> Some v | _ :: t -> findOpt x t ;; findOpt "d" al ;; (* Immutable maps *) (* Immutable maps can be obtaining by instantiating a generic Map module by a type for the map index *) module Dictionary = Map.Make(String) ;; let m = Dictionary.empty ;; let m1 = Dictionary.add "a" 1 m let m3 = Dictionary.add "b" 3 (Dictionary.add "d" 6 m1) (* incremental map construction using pipes *) let m4 = Dictionary.empty |> Dictionary.add "a" 1 |> Dictionary.add "b" 3 |> Dictionary.add "c" 0 let m5 = Dictionary.remove "b" m4 ;; m4 ;; (* exception raising find *) Dictionary.find "b" m4 ;; Dictionary.find "b" m5 ;; (* option returning find *) Dictionary.find_opt "b" m5 ;; Dictionary.find_opt "b" m4 ;; (* mutable variables *) (* mutable variables can be simulated by a record with one mutable field *) type 'a mvar = { mutable value : 'a } ;; let z = {value = 0} ;; z.value <- 11 ;; (* // assignments are expressions that have value () // the value is not interesting, we evaluate assignment only for // their side effect (changing the value of a mutable variable) *) let a = {value = 1} ;; let b = {value = 2} let x = a.value <- 3 ;; x ;; (* expression sequences *) (* operator ; is an infix binary operator that takes an expression of type unit and an expression of any type, evaluates them in order and returns the value of the second *) () ; 5 (* evaluates to 5 *) ;; () ; (1+4) (* also evaluates to 5 *) ;; let u = () ;; (* ; is associative: all these evaluate to 5 *) u ; u ; 5 ;; (u ; u) ; 5 ;; u ; (u ; 5) ;; (* ; is interesting only with expression that have *side effects* such as assignments *) a.value <- 4; 5 ;; (* assigns 7 to a, assigns 8 to b, returns () *) a.value <- 7; b.value <- 8 ;; a;; let f x = if x > 0 then ( a.value <- 10; b.value <- 11 ) else () ;; f 4 ;; a ;; b ;; (* while loops *) a.value <- 6 ;; while (a.value > 0) do Printf.printf "%i\n\n" a.value; a.value <- a.value - 1 done ;; while (a.value > 0) do Printf.printf "%i\n\n" a.value; a.value <- a.value - 1 done