欢迎访问yhm138的博客园博客, 你可以通过 [RSS] 的方式持续关注博客更新

MyAvatar

yhm138

HelloWorld!

OCaml编程示例

个人感觉,写OCaml要比写那些纯粹函数式编程语言(Haskell,Elixir,Erlang)容易一点。

逻辑控制语句及循环控制语句

TIO

(* 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

TIO

(* 常用的列表操作 *)

(* 使用 :: 操作符创建一个新的列表 *)
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

TIO

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

TIO

(* 定义一个基础的 '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
  }
}

函数式OCaml代码

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]] *)

过程式OCaml代码

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);
;;

posted @ 2023-08-29 20:29  yhm138  阅读(39)  评论(0编辑  收藏  举报