diff --git a/.gitignore b/.gitignore index 478d91f..0021882 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,6 @@ *.cmo *.cmi *.zip +*.native +*/_build/* diff --git a/lecture05/cat.ml b/lecture05/cat.ml new file mode 100644 index 0000000..614d4c9 --- /dev/null +++ b/lecture05/cat.ml @@ -0,0 +1,26 @@ +(* display content of file read via stdin *) +let rec cat () = + try + let line = read_line () in + print_endline line; + cat() + with + | _ -> ();; (* EOF return unit *) + +(* similar to main function *) +let () = + let rec aux () = + try + print_endline @@ read_line (); + aux () + with + | _ -> () + in + aux() + (* cat() *) + +(**** build and test ****) +(* + ocamlbuild cat.native + ./cat.native < filename +*) diff --git a/lecture05/data.txt b/lecture05/data.txt new file mode 100644 index 0000000..9f57138 --- /dev/null +++ b/lecture05/data.txt @@ -0,0 +1,4 @@ +123 456 +-123 -456 +abc +25 diff --git a/lecture05/echo.ml b/lecture05/echo.ml new file mode 100644 index 0000000..b2774fd --- /dev/null +++ b/lecture05/echo.ml @@ -0,0 +1,6 @@ +let () = + let len = Array.length Sys.argv - 1 in + for i = 1 to len do + Printf.printf (if i <> len then "%s " else "%s\n") Sys.argv.(i) + done;; + diff --git a/lecture05/notes.ml b/lecture05/notes.ml new file mode 100644 index 0000000..bdf4153 --- /dev/null +++ b/lecture05/notes.ml @@ -0,0 +1,161 @@ +(**** RECORDS ****) +type student = {id: string; name: string; gpa: float};; + +let s1 = {id = "a12345678"; name = "homer simpson"; gpa = 25.5};; +let make_student id name gpa = { id = id; name = name; gpa = gpa };; +let s2 = make_student "a000000" "monty burns" 99.9;; + +(* defining a function to return the name field of a record *) +let name {id = id; name = name; gpa = gpa} = name;; +let name {id; name; gpa} = name;; +let name {name} = name;; +let name s = s.name;; + +name s2;; + +type instructor = {id: string; name: string; salary: float};; +let i1 = {id = "a777777"; name = "lisa simpson"; salary = 100000.};; + +(* name cannot be applied to constructor because name was defined before instructor + and it deferred from student *) +(* name i1;; *) + +let id x = x.id;; + +(* id s1;; <-- this doesnt work because id infers from the latest defined, such as instructor *) +id i1;; + +type isntr = Instructor of {id: string; name: string; salary: float};; +let i1 = Instructor {id = "a777777"; name = "lisa simpson"; salary = 100000.};; + +let s1 = make_student "a123456678" "homer simpson" 25.5;; +let s2 = s1;; (* s2 is its own student it just shares the same data *) +let s2 = {s1 with id = "a22222222"; name = "bart simpson"} (* this allows us to copy data and modify selected data *) + +(**** MUTABILITY - you can mark fields as mutable ****) +type student = {id: string; name: string; mutable gpa: float};; +let make_student id name gpa = { id = id; name = name; gpa = gpa };; +let s1 = make_student "a123456678" "homer simpson" 25.5;; +let s2 = s1;; (* refer to the same thing *) + +s2;; + +(* update field for s1 *) +s1.gpa <- 15.5; + +(* shows changes applied to s1 since s2 refers to the same data *) +s2;; + +(**** REFERENCES & DEREFEREMCES ****) +let x = ref 1;; +!x;; (* deref *) +x := 2;; (* update val of references *) +x;; +!x;; + +let y = x;; +y;; +x;; +incr x;; (* y is the same as x (ref to int) so updating x also shows in y *) +x;; +y;; + +let x = ref (Some 1);; +let y = ref None;; +(* val y : '_wek1 option ref = {contents = None} *) +(* curremtly the contents of y are weakly polymorphic + because it can be any type. the type inference cannot + deduce the value of the optional *) +y := Some 2;; +y;; +(* - : int option ref = {contents = Some 1} *) + +(**** ARRAYS - arrays are mutable ****) +[|1;2;3;3;4;5|];; (* arrays have vertical bars unlike lists *) +let a = [|1;2;3|];; +a.(0);; (* get first element *);; +a.(1);; +a.(2);; +(* a.(3);; (* Invalid_argument excetption *) *) + +a.(0) <- -1;; +a;; + +(**** FOR / WHILE LOOPS ****) +(* for loops on arrays... yikes *) +Array.length a;; +for i = 0 to Array.length a - 1 do + a.(i) <- 2 * a.(i) +done;; + +a;; + +(* you can go in reverse also using downto *) +for i = Array.length a - 1 downto 0 do + a.(i) <- 2 * a.(i) +done;; + +(* while loops also... *) +let i = ref 0;; +while !i < Array.length a do + (* adding semi-colon to end of expression means + this is a garbage value, throw it away so we + dont return unit() type early *) + a.(!i) <- - !i; + incr i +done;; + +a;; + +(**** IGNORE ****) +(* x will be 2 and the expression 1; + is ignored because of the semi-colon *) +let x = ignore 1; 2;; + +(**** EXCEPTIONS ****) +(* defining exceptions and rasing *) +(* exception is a variant type and the + number of variants can be extended *) +(* exception Hell;; *) +(* raise Hell;; +Failure "hell";; *) + +(* exceptions can have parameters *) +exception Hell of int;; +Hell 1;; +Hell 2;; + +(* List.hd [];; (* raises an exception *) *) + +(* you can pattern match exceptions with try-with *) +try + List.hd [] +with +| Failure _ -> -1;; + +try + List.hd [] +with +| _ -> -1;; + + +(**** IO ****) +print_string "hello world\n";; +print_endline "hello world";; +print_int 123;; +print_float 123.4;; +print_newline ();; +Printf.printf "%5d\n" 123;; +Printf.printf "%05d %s\n" 123 "hello";; +Printf.eprintf "%05d %s\n" 123 "hello";; (* print to standard error channel *) + +let x = read_line ();; + +(* read in int - add space at the front, it matches any amount of leading whitespace *) +Scanf.scanf " %d" (fun x -> x) + +(* open file *) +(* open_in "filename";; *) +let ic = open_in "output";; +input_line ic;; + diff --git a/lecture05/number_file_lines.ml b/lecture05/number_file_lines.ml new file mode 100644 index 0000000..477043c --- /dev/null +++ b/lecture05/number_file_lines.ml @@ -0,0 +1,16 @@ +let rec number acc ic = + try + Printf.printf "%5d| %s\n" acc @@ input_line ic; + number (acc + 1) ic + with + | _ -> if ic <> stdin then close_in ic else () + +let () = + if Array.length Sys.argv = 1 then + number 1 stdin + else + try + number 1 @@ open_in Sys.argv.(1) + with + | Sys_error s -> Printf.eprintf "%s\n" s;; + diff --git a/lecture05/number_lines.ml b/lecture05/number_lines.ml new file mode 100644 index 0000000..4028e41 --- /dev/null +++ b/lecture05/number_lines.ml @@ -0,0 +1,9 @@ +let () = + let rec aux acc = + try + Printf.printf "%5d| %s\n" acc @@ read_line (); + aux (acc + 1) + with + | _ -> () + in + aux 1;; diff --git a/lecture05/output b/lecture05/output new file mode 100644 index 0000000..3b18e51 --- /dev/null +++ b/lecture05/output @@ -0,0 +1 @@ +hello world diff --git a/lecture05/ref.ml b/lecture05/ref.ml new file mode 100644 index 0000000..d3b62cf --- /dev/null +++ b/lecture05/ref.ml @@ -0,0 +1,12 @@ +(* we can impliment our own ref type *) +type 'a ref = { mutable contents: 'a };; + +(* reference and dereference implimentation *) +let ref x = { contents = x };; +let (!) r = r.contents;; + +(* assign to a mutable field *) +let (:=) r x = r.contents <- x;; + +let incr r = r.contents <- r.contents + 1;; +let decr r = r.contents <- r.contents - 1;; diff --git a/lecture05/sum_integers.ml b/lecture05/sum_integers.ml new file mode 100644 index 0000000..d9b5fac --- /dev/null +++ b/lecture05/sum_integers.ml @@ -0,0 +1,12 @@ +let () = + let rec aux sum = + try + aux @@ Scanf.scanf " %d" (fun x -> sum + x) + with + | Scanf.Scan_failure _ -> + Scanf.scanf " %s" (fun _ -> ()); + aux sum + | End_of_file -> sum + in + Printf.printf "%d\n" @@ aux 0;; +