Content is user-generated and unverified.
(* ==================== *) (* LIST OPERATIONS *) (* ==================== *) (* Standard Library - What you CAN do *) let numbers = [1; 2; 3; 4; 5] (* Basic list operations work fine *) let doubled = List.map (fun x -> x * 2) numbers let evens = List.filter (fun x -> x mod 2 = 0) numbers let sum = List.fold_left (+) 0 numbers (* Standard Library - What's MISSING or AWKWARD *) (* 1. No built-in list chunking *) let rec chunk n lst = match lst with | [] -> [] | _ -> let rec take acc n lst = if n = 0 || lst = [] then (List.rev acc, lst) else take (List.hd lst :: acc) (n-1) (List.tl lst) in let (chunk, rest) = take [] n lst in chunk :: chunk rest (* 2. No easy way to get last element *) let rec last = function | [] -> failwith "empty list" | [x] -> x | _ :: xs -> last xs (* 3. No built-in deduplication *) let dedup lst = let rec aux acc seen = function | [] -> List.rev acc | x :: xs -> if List.mem x seen then aux acc seen xs else aux (x :: acc) (x :: seen) xs in aux [] [] lst (* With Base - Much cleaner *) #require "base";; open Base let numbers = [1; 2; 3; 4; 5] (* Same basic operations *) let doubled = List.map numbers ~f:(fun x -> x * 2) let evens = List.filter numbers ~f:(fun x -> x % 2 = 0) let sum = List.fold numbers ~init:0 ~f:(+) (* But now you get many more utilities *) let chunks = List.chunks_of numbers ~len:2 let last_elem = List.last numbers (* Returns option *) let deduped = List.dedup_and_sort numbers ~compare:Int.compare (* ==================== *) (* STRING OPERATIONS *) (* ==================== *) (* Standard Library - Limited string functions *) let text = "hello,world,ocaml" (* Basic string operations *) let length = String.length text let substring = String.sub text 0 5 (* Splitting strings requires manual work or external libraries *) let split_on_char c s = let rec aux acc start i = if i >= String.length s then if start < i then (String.sub s start (i - start)) :: acc else acc else if s.[i] = c then let substring = String.sub s start (i - start) in aux (substring :: acc) (i + 1) (i + 1) else aux acc start (i + 1) in List.rev (aux [] 0 0) let words = split_on_char ',' text (* With Base - Rich string API *) let text = "hello,world,ocaml" let words = String.split text ~on:',' let prefixed = List.map words ~f:(String.prefix ~len:3) let joined = String.concat words ~sep:" | " let stripped = String.strip " hello " (* ==================== *) (* OPTION HANDLING *) (* ==================== *) (* Standard Library - Basic option support *) let maybe_value = Some 42 let result = match maybe_value with | None -> 0 | Some x -> x * 2 (* Chaining operations requires manual pattern matching *) let safe_divide x y = if y = 0 then None else Some (x / y) let compute x y z = match safe_divide x y with | None -> None | Some result1 -> match safe_divide result1 z with | None -> None | Some result2 -> Some (result2 + 1) (* With Base - Rich option combinators *) let maybe_value = Some 42 let result = Option.value maybe_value ~default:0 |> fun x -> x * 2 (* Monadic operations *) let compute x y z = safe_divide x y >>= fun result1 -> safe_divide result1 z >>| fun result2 -> result2 + 1 (* Or with let syntax *) let compute x y z = let%bind result1 = safe_divide x y in let%bind result2 = safe_divide result1 z in return (result2 + 1) (* ==================== *) (* COMPARISON & EQUALITY *) (* ==================== *) (* Standard Library - Polymorphic comparison can be problematic *) let compare_tuples (a, b) (c, d) = let cmp1 = compare a c in if cmp1 <> 0 then cmp1 else compare b d (* With Base - Systematic comparison *) module Person = struct type t = { name: string; age: int } [@@deriving compare, sexp] end let people = [ { Person.name = "Alice"; age = 30 }; { Person.name = "Bob"; age = 25 } ] let sorted_people = List.sort people ~compare:Person.compare (* ==================== *) (* RESULT TYPE *) (* ==================== *) (* Standard Library - No built-in Result type (before OCaml 4.03) *) type ('a, 'e) result = Ok of 'a | Error of 'e let safe_parse s = try Ok (int_of_string s) with Failure _ -> Error "not a number" (* Manual result chaining *) let process_numbers s1 s2 = match safe_parse s1 with | Error e -> Error e | Ok n1 -> match safe_parse s2 with | Error e -> Error e | Ok n2 -> Ok (n1 + n2) (* With Base - Rich Result API *) let safe_parse s = try Ok (Int.of_string s) with _ -> Error "not a number" let process_numbers s1 s2 = Result.both (safe_parse s1) (safe_parse s2) |> Result.map ~f:(fun (n1, n2) -> n1 + n2) (* ==================== *) (* HASH TABLES *) (* ==================== *) (* Standard Library - Basic hashtable *) let table = Hashtbl.create 16 let () = Hashtbl.add table "key1" "value1" let value = try Some (Hashtbl.find table "key1") with Not_found -> None (* With Base - More consistent API *) let table = Hashtbl.create (module String) let () = Hashtbl.set table ~key:"key1" ~data:"value1" let value = Hashtbl.find table "key1" (* Returns option *) (* ==================== *) (* FUNCTIONAL UTILITIES *) (* ==================== *) (* Standard Library - Missing many functional programming utilities *) (* No built-in function composition *) let compose f g x = f (g x) let (>>>) f g = compose g f (* No pipe operator *) let result = [1; 2; 3; 4; 5] |> List.map (fun x -> x * 2) |> List.filter (fun x -> x > 5) |> List.fold_left (+) 0 (* With Base - Rich functional programming support *) let (|>) x f = f x (* Pipe operator *) let result = [1; 2; 3; 4; 5] |> List.map ~f:(fun x -> x * 2) |> List.filter ~f:(fun x -> x > 5) |> List.fold ~init:0 ~f:(+) (* Function composition *) let process = Fn.compose (fun x -> x * 2) (fun x -> x + 1) (* ==================== *) (* SUMMARY *) (* ==================== *) (* What you CAN do with just OCaml standard library: - Basic data structure operations (lists, arrays, strings) - Pattern matching and algebraic data types - Module system - Basic I/O operations - Exception handling - All core language features What Base adds: - Consistent, labeled arguments (~f:, ~init:, etc.) - Rich utility functions for common operations - Better error handling with Option and Result combinators - Systematic comparison and serialization with ppx - More functional programming utilities - Performance improvements - Consistent API design across all data structures - Better ergonomics for everyday programming tasks The standard library is functional but requires more boilerplate and manual implementation of common patterns that Base provides out of the box. *)
Content is user-generated and unverified.
    OCaml Standard Library vs Base Examples | Claude