Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- (* filemerge.ml *)
- type sortrecord = { line: string; f: in_channel }
- let basename = let argv0 = Array.get Sys.argv 0 in
- let first = (String.rindex argv0 '/') + 1 in
- let len = (String.length argv0) - first in
- String.sub argv0 first len;;
- let ( |! ) a b = b a ;;
- (* filemerge: merge sort the provided list of pre-sorted files and write
- * the result to stdout *)
- (** string list -> unit **)
- let rec filemerge filenames =
- (* recharge: Creates a new sortrecord list with the next line
- * from the given channel; or an empty list, if the channel has
- * closed. *)
- (** in_channel -> sortrecord list **)
- let recharge fd =
- try
- Some {
- line = input_line fd;
- f = fd
- }
- with
- End_of_file ->
- close_in_noerr fd;
- None
- in
- (* work: Recursively spit out lines until all the files are gone *)
- (* sortrecord list -> unit *)
- let rec work units =
- match
- List.fold_left
- (fun accum x ->
- match accum with
- | [] -> [x]
- | winner :: rest ->
- if compare x.line winner.line < 0
- then x :: winner :: rest
- else winner :: x :: rest
- )
- []
- units
- with
- | [] -> ()
- | hd :: tl ->
- print_endline hd.line;
- (match recharge hd.f with
- | Some x -> work (x :: tl)
- | None -> work tl
- )
- in
- work (
- List.map open_in filenames
- |! List.map recharge
- |! List.filter (function Some _ -> true | None -> false)
- |! List.map (function Some x -> x | None -> failwith "bug")
- )
- ;;
- let () =
- match Array.to_list Sys.argv with
- | [] -> failwith "no arg0 wtf"
- | _ :: [] -> Printf.printf "Usage: %s [file1 .. fileN]\n" basename
- | _ :: files -> filemerge files
- ;;
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement