Article
OCaml学习
记录学习OCaml的过程中的知识点.
dune build --watch
value: an expression for which there is no computation to be performed
Primary Task of Computation : evaluate an expression to a value
Fail to evaluate an expression to a value: (1) => raises an exception (2) => infinite loop
int: ocaml Integers ranges from $-2^{62} \sim 2^{62} - 1$, 1 bit is used at run time to distinguish integers from pointers (garbage collector)
float : 3. / 3.0 / 3.14
operations between float 3. *. 2.
bool : true / false
char: ‘a’, ‘b’, ‘c’… (represented as bytes, i.e. 8-bit integers)
string: sequence of chars (concat “abc” ^ “def”). (string_to_int, string_to_float, string_to_bool …) no string_to_char but have String.make
no char_to_string but have “aes”.[1]
’=’ and ’<>’ examine structural equality ’==’ and ’!=’ examine physical equality
assert e => evaluate e, if true, the res of assert e is a special value called ’()’, type ‘unit’
evaluation rules: define how to evaluate expressions typing rules: describes how to type check an expression.
e(metavariable) has type t(metavariable) <=> e : t
let x = 42 # definition let x = 42 in x # expression, bind 42 to x and use it in x expression
let a = 42;; <=> let a = 42 in
alpha equivalence : the two funcs are equivalent up to renaming of variables.
![[Pasted image 20260817192402.png]]
let f x = … (definition of func) let rec f x = … (definition of recursive func)
mutually recursive func:
let rec f x1 ... xn = e1
and g y1 ... yn = e2
anonymous functions(lambda functions)
useful in higher-order programming
keyword fun
let inc = func x -> x + 1
lambda calculus
(func x -> e1) e2
and
let x = e1 in e2
they are syntactically different but semantically equivalent
Pipeline 一种内置的特殊中缀运算符
5 |> inc |> square
Polymorphic functions
let id x = x
type of id is 'a -> 'a
let id_int : int -> int = id
这个是把一个'a -> 'a类型的表达式赋值给了一个'int -> 'int类型的表达式, 可以这么考虑这件事, 'int -> 'int只是'a -> 'a 所有可能的行为中的一种, 只是其他的可能行为被丢掉了.
labeled and optional arguments
(**labeled arguments**)
let f ~name1:(arg1 : int) ~name2:(arg2 : int) = arg1 + arg2
let f ~name1 ~name2 = name1 + name2
(**optional arguments**)
let f ?name1:(arg1=8) name2(arg2) = arg1 + arg2
Partial Application
let add x y = x + y
let addx x = fun y -> x + y
let add = fun x -> (fun y -> x + y)
Every OCaml function takes exactly one argument
function types are right associative
function application is left associative
f : X -> (Y -> Z)
f x y z <=> (((f x) y) z)
Define our own infix operator
let ( ^^ ) x y = max x y
2 ^^ 3
Tail Recursion
let rec count_n n = if n = 0 then 0 else 1 + count_n (n - 1)
this will run out of memory of stack space when n is large
Tail Recursion Optimization
let rec count_aux n acc = if n = 0 then acc else count_aux (n - 1) (acc + 1)
let count_tr n = count_aux n 0
Why tail position matters: A recursive call in tail position does not need a new stack frame. (No computation left to be done.)
compiler should support tail recursive Optimization (Java not support)
example:
let rec fact n = if n = 0 then 1 else n * fact (n - 1)
tr version
let rec fact_helper n acc = if n = 0 then acc else fact_helper (n - 1) (n * acc)
let fact_tr n = fact_helper n 1
Zarith OCaml’s big integer lib
** -> comment to be recognized as an OCamldoc comment
() -> be rendered in HTML as typewriter font
side effect -> changes the world and can’t be undone
print_endline "are";
e1 ; e2 -> evaluates e1, then discard that value, and evaluates e2
ignore ‘a -> unit
Debugging
How to discovered bugs
-
Memory Safety and Type Safety language
-
Use tools to find bugs
-
Fail fast
-
Write automated code tests
After discovered bugs
-
Distill the bug into a small test case
-
Employ the scientific method
-
Fix the bug
-
Add the small test case from step 1 in test suite
Debugging in OCaml
- Print statement
let inc x =
let () = print_endline x in
x + 1
这个作为一个整体是一个definition, 然后let () = print_endline x in x + 1是一个expression
Function traces
let rec fib x = if x <= 1 then 1 else fib (x - 1) + fib (x - 2)
#trace fib;;
use #untrace to stop trace func
Defensive Programming
let random_int bound =
if not (bound > 0 && bound < 1 lsl 30)
then invalid_arg "bound";to be continued...