OCaml编程示例
个人感觉,写OCaml要比写那些纯粹函数式编程语言(Haskell,Elixir,Erlang)容易一点。
逻辑控制语句及循环控制语句
(* if...then...else 语句 *)
let x = 5 in
if x > 0 then
print_endline "x is positive"
else
print_endline "x is non-positive";;
(* match...with 语句,用于模式匹配 *)
let y = 3 in
match y with
| 1 -> print_endline "one"
| 2 -> print_endline "two"
| _ -> print_endline "other";; (* '_' 模式匹配所有其他可能性 *)
(* for 循环 *)
for i = 1 to 10 do
print_endline (string_of_int i)
done;;
(* while 循环 *)
let z = ref 10 in
while !z > 0 do
print_endline (string_of_int !z);
z := !z - 1
done;;
函数式编程FP
(* 常用的列表操作 *)
(* 使用 :: 操作符创建一个新的列表 *)
let numbers = 1 :: 2 :: 3 :: 4 :: 5 :: []
(* 使用 List.map 函数来对列表中的每一个元素进行操作 *)
let doubled_numbers = List.map (fun x -> x * 2) numbers
(* 使用 List.filter 函数来过滤列表中的元素 *)
let even_numbers = List.filter (fun x -> x mod 2 = 0) numbers
(* 使用 List.fold_left 函数来对列表进行折叠操作 *)
let sum = List.fold_left (fun acc x -> acc + x) 0 numbers
(* 常用的模式匹配操作 *)
(* 使用 match...with 来进行模式匹配 *)
let rec factorial n =
match n with
| 0 -> 1
| _ -> n * factorial (n-1)
(* 使用 function 关键字可以简化模式匹配 *)
let rec factorial = function
| 0 -> 1
| n -> n * factorial (n-1)
(* 常用的递归函数 *)
(* 使用 let rec 来定义递归函数 *)
let rec fibonacci n =
if n < 2 then n
else fibonacci (n-1) + fibonacci (n-2)
(* 使用和模式匹配结合的递归函数 *)
let rec length = function
| [] -> 0
| _ :: tail -> 1 + length tail
(* 打印结果 *)
let () =
print_string "Doubled numbers: ";
List.iter (fun n -> print_int n; print_string " ") doubled_numbers;
print_newline ();
print_string "Even numbers: ";
List.iter (fun n -> print_int n; print_string " ") even_numbers;
print_newline ();
print_string "Sum: ";
print_int sum;
print_newline ();
print_string "Factorial of 5: ";
print_int (factorial 5);
print_newline ();
print_string "Fibonacci of 10: ";
print_int (fibonacci 10);
print_newline ();
print_string "Length of numbers: ";
print_int (length numbers);
print_newline ()
常用Collection
module Int = struct
type t = int
let compare = Pervasives.compare
end
module IntMap = Map.Make(Int);; (* 创建一个整数Map模块 *)
module IntSet = Set.Make(Int);; (* 创建一个整数Set模块 *)
(* OCaml 的列表是不可变的。 *)
let list_example () =
let lst = [1; 2; 3; 4; 5] in (* 创建一个列表 *)
let lst = List.append lst [6; 7; 8; 9; 10] in (* 追加元素到列表 *)
List.iter (fun x -> print_int x; print_newline ()) lst (* 迭代列表并打印每个元素 *)
;;
(* OCaml 的数组是可变的。 *)
let array_example () =
let arr = Array.init 10 (fun i -> i * i) in (* 创建一个数组并初始化 *)
Array.iteri (fun i x -> print_string ("arr[" ^ string_of_int i ^ "] = " ^ string_of_int x ^ "\n")) arr (* 迭代数组并打印每个元素 *)
;;
(* OCaml 的字符串是不可变的。 *)
let string_example () =
let str = "Hello, OCaml!" in (* 创建一个字符串 *)
print_string (str ^ "\n") (* 打印字符串 *)
;;
let set_example () =
let open IntSet in
let s = empty in (* 创建一个空集合 *)
let s = add 1 (add 2 (add 3 s)) in (* 添加元素到集合 *)
iter (fun x -> print_int x; print_newline ()) s (* 迭代集合并打印每个元素 *)
;;
let map_example () =
let open IntMap in
let m = empty in (* 创建一个空映射 *)
let m = add 1 "one" (add 2 "two" (add 3 "three" m)) in (* 添加元素到映射 *)
iter (fun k v -> print_string (string_of_int k ^ " -> " ^ v ^ "\n")) m (* 迭代映射并打印每个元素 *)
;;
(* 运行所有的例子 *)
let () =
list_example ();
array_example ();
string_example ();
set_example ();
map_example ()
;;
面向对象编程OOP
(* 定义一个基础的 'shape' 类。 *)
class virtual shape x_init y_init =
object
val mutable x = x_init
val mutable y = y_init
method get_x = x
method get_y = y
method virtual area : float
method move dx dy = x <- x +. dx; y <- y +. dy
end
(* 定义一个 'circle' 类,继承自 'shape' 类,并添加一个 'radius' 字段。 *)
class circle x y radius =
object
inherit shape x y
val mutable r = radius
method area = 3.14159 *. r *. r
method enlarge m = r <- r *. m
end
(* 定义一个 'rectangle' 类,继承自 'shape' 类,并添加 'width' 和 'height' 字段。 *)
class rectangle x y width height =
object
inherit shape x y
val mutable w = width
val mutable h = height
method area = w *. h
end
(* 使用类 *)
let _ =
let c = new circle 0.1 0.2 1.5 in
let r = new rectangle 0.0 0.0 1.4 2.3 in
Printf.printf "Circle area: %f\n" c#area;
Printf.printf "Rectangle area: %f\n" r#area;
c#move 0.2 0.3;
Printf.printf "Circle new position: (%f, %f)\n" c#get_x c#get_y;
LeetCode 57.插入区间
将现有的Scala代码改成2份Ocaml代码,一份函数式,一份过程式。
object Solution {
def insert(intervals: Array[Array[Int]], newInterval: Array[Int]): Array[Array[Int]] = {
var (left, right) = (newInterval(0), newInterval(1))
var placed = false
val ansList = scala.collection.mutable.ListBuffer[Array[Int]]()
for (interval <- intervals) {
if (interval(0) > right) {
// On the right side of the insertion interval and no intersection
if (!placed) {
ansList += Array(left, right)
placed = true
}
ansList += interval
} else if (interval(1) < left) {
// On the left side of the insertion interval and no intersection
ansList += interval
} else {
// Overlapping with the insertion interval, compute their union
left = Math.min(left, interval(0))
right = Math.max(right, interval(1))
}
}
if (!placed) {
ansList += Array(left, right)
}
ansList.toArray
}
}
let insert intervals new_interval =
let left, right = new_interval in
let rec helper intervals placed left right ans_list =
match intervals with
| [] ->
if not placed then
Array.of_list ((left, right)::ans_list)
else
Array.of_list ans_list
| interval::rest ->
let iv_left, iv_right = interval in
if iv_left > right then
(* On the right side of the insertion interval and no intersection *)
if not placed then
helper rest true left right ((left, right)::interval::ans_list)
else
helper rest placed left right (interval::ans_list)
else if iv_right < left then
(* On the left side of the insertion interval and no intersection *)
helper rest placed left right (interval::ans_list)
else
(* Overlapping with the insertion interval, compute their union *)
let left = min left iv_left in
let right = max right iv_right in
helper rest placed left right ans_list
in
helper (Array.to_list intervals) false left right []
let () =
let print_intervals intervals =
print_string "[";
intervals |> Array.iter (fun (left, right) -> Printf.printf "[%d,%d]; " left right);
print_endline "]";
in
let test_intervals = [|(1,3); (6,9)|] in
let new_interval = (2,5) in
print_intervals (insert test_intervals new_interval); (* Output: [[1,5]; [6,9]] *)
let test_intervals = [|(1,2); (3,5); (6,7); (8,10); (12,16)|] in
let new_interval = (4,8) in
print_intervals (insert test_intervals new_interval); (* Output: [[1,2]; [3,10]; [12,16]] *)
let test_intervals = [||] in
let new_interval = (5,7) in
print_intervals (insert test_intervals new_interval); (* Output: [[5,7]] *)
let test_intervals = [|(1,5)|] in
let new_interval = (2,3) in
print_intervals (insert test_intervals new_interval); (* Output: [[1,5]] *)
let test_intervals = [|(1,5)|] in
let new_interval = (2,7) in
print_intervals (insert test_intervals new_interval); (* Output: [[1,7]] *)
let insert intervals new_interval =
let left = ref (fst new_interval) in
let right = ref (snd new_interval) in
let placed = ref false in
let ans_list = ref [] in
List.iter (fun (l, r) ->
if l > !right then
begin
if not !placed then
begin
ans_list := (!left, !right) :: !ans_list;
placed := true
end;
ans_list := (l, r) :: !ans_list
end
else if r < !left then
ans_list := (l, r) :: !ans_list
else
begin
left := min !left l;
right := max !right r;
end
) intervals;
if not !placed then
ans_list := (!left, !right) :: !ans_list;
List.rev !ans_list
;;
(* Test Cases *)
let () =
let print_intervals intervals =
List.iter (fun (l, r) -> Printf.printf "[%d,%d] " l r) intervals;
print_newline ()
in
let intervals1 = [(1,3); (6,9)] and new_interval1 = (2,5) in
let intervals2 = [(1,2); (3,5); (6,7); (8,10); (12,16)] and new_interval2 = (4,8) in
let intervals3 = [] and new_interval3 = (5,7) in
let intervals4 = [(1,5)] and new_interval4 = (2,3) in
let intervals5 = [(1,5)] and new_interval5 = (2,7) in
print_intervals (insert intervals1 new_interval1);
print_intervals (insert intervals2 new_interval2);
print_intervals (insert intervals3 new_interval3);
print_intervals (insert intervals4 new_interval4);
print_intervals (insert intervals5 new_interval5);
;;