File Paths in OCaml

Here’s the translation of the Go code example to OCaml, with explanations in Markdown format suitable for Hugo:

The Filename module in OCaml provides functions to manipulate file names and paths in a way that is portable between operating systems.

open Printf

let main () =
  (* Join should be used to construct paths in a portable way. *)
  let p = Filename.concat "dir1" (Filename.concat "dir2" "filename") in
  printf "p: %s\n" p;

  (* You should always use concat instead of concatenating
     '/' or '\' manually. In addition to providing portability,
     concat will also normalize paths. *)
  printf "%s\n" (Filename.concat "dir1//" "filename");
  printf "%s\n" (Filename.concat "dir1/../dir1" "filename");

  (* dirname and basename can be used to split a path to the
     directory and the file. *)
  printf "Dir(p): %s\n" (Filename.dirname p);
  printf "Base(p): %s\n" (Filename.basename p);

  (* We can check whether a path is absolute. *)
  printf "%b\n" (Filename.is_relative "dir/file");
  printf "%b\n" (Filename.is_relative "/dir/file");

  let filename = "config.json" in

  (* Some file names have extensions following a dot. We
     can split the extension out of such names with extension_of. *)
  let ext = Filename.extension filename in
  printf "%s\n" ext;

  (* To find the file's name with the extension removed,
     use chop_extension. *)
  printf "%s\n" (Filename.chop_extension filename);

  (* OCaml doesn't have a direct equivalent to Go's filepath.Rel,
     but we can implement a simple version using Unix module. *)
  let rel base target =
    let rec aux acc base target =
      match base, target with
      | [], [] -> String.concat "/" (List.rev acc)
      | [], t -> String.concat "/" (List.rev_append acc t)
      | _, [] -> String.concat "/" (List.rev_append acc (List.map (fun _ -> "..") base))
      | b::bs, t::ts when b = t -> aux acc bs ts
      | _ -> aux (".." :: acc) bs target
    in
    aux [] (String.split_on_char '/' base) (String.split_on_char '/' target)
  in

  printf "%s\n" (rel "a/b" "a/b/t/file");
  printf "%s\n" (rel "a/b" "a/c/t/file")

let () = main ()

To run the program, save it as file_paths.ml and use ocamlc to compile it:

$ ocamlc -o file_paths file_paths.ml
$ ./file_paths
p: dir1/dir2/filename
dir1/filename
dir1/filename
Dir(p): dir1/dir2
Base(p): filename
true
false
.json
config
t/file
../c/t/file

This OCaml program demonstrates file path manipulation using the Filename module. It shows how to join paths, extract directory and file names, check for relative paths, handle file extensions, and perform relative path calculations.

Note that OCaml’s standard library doesn’t provide a direct equivalent to Go’s filepath.Rel function, so a simple implementation is provided. For more complex path manipulations, you might want to use additional libraries or implement more robust functions.