Intro
Col is a syntax library for OCaml for a compact and safe definition of IO functions on lists of flat records.
One type definition in a record-like syntax is expanded into a regular type definition of a record type, a tuple type and a class, plus many conversion functions which would have to be written manually otherwise. List of such objects can be loaded from and saved to CSV files with a header describing each field (column). You can edit these files manually, possibly by inserting new columns, and yet these files remain readable by your program.
See http://martin.jambon.free.fr/col-doc.html for an illustration of a program and the result after preprocessing. Hopefully it is self-explanatory. You can notice that the interface (doc.mli) which is automatically generated is much longer than the source implementation (doc.ml ~80 lines). After preprocessing, the implementation (doc.ppo) is truly huge (~800 lines), so it might take a while to compile.
Documentation
There is no documentation but there is a complete example at http://martin.jambon.free.fr/col-doc.html
Changes
version 1.1.1:
- added support for predefined record and variant types, i.e. it defines functions that work over an existing type from a given library; this is done by inserting a new "predefined" keyword after the equal sign;
- added support for traditional variants, mostly for compatibility with existing libraries that don't use polymorphic variants.
version 1.1.0: added functions for custom sort. Modules which are used to define custom types must now define a comparison function named "compare" (use "let compare = compare" if you want to use OCaml's default or if you don't want to use the comparison functions).
Examples
Here is a short example which defines a list of 2 records and saves them:
(* File test.ml *)
type col t = { x : float;
y : float;
title "The Title" : string = "no title" }
let data =
let x = 1. in
[ T.create ~x ~y:2. ();
T.create ~y:4. ~x ~title:"line2" () ]
let _ = T.save_csv "data.csv" data
$ ocamlfind ocamlopt -o testcol test.ml -syntax camlp4o -package col -linkpkg
$ ./testcol
$ cat data.csv
x,y,"The Title"
1.,2.,"no title"
1.,4.,line2
$
Bugs
Installation
There is a bug in OCaml 3.09.1 which prevents from pr_o.cmo from working correctly (Stack overflow while executing something like "camlp4o pr_o.cmo ..."). The bug is not present in 3.08.4 and has been fixed in 3.09.2. If you are having this problem, compile with:
(instead of "make" alone)
User Questions
Could you give an example of loading col from the toplevel using ocamlfind?
A: Like other findlib packages that provide a camlp4 syntax extension, you have to specify manually that you want to use "camlp4o", which correspond to the regular OCaml syntax support in camlp4. Actually I don't know if it would be possible to define a findlib package or sub-package that would do this automatically. Anyway the steps are the following:
- #use "topfind";;
- #camlp4o;;
- #require "col";;
Note that if you are just interested in knowing which types and functions are made available by a given "type col" definition, using ocamlc or ocamlopt with the -i option may be a better choice than using the toplevel, e.g.
ocamlfind ocamlopt -i -syntax camlp4o -package col yourfile.ml > yourfile.mli
Here is a simple toplevel session; as you can see, the output is long:
Objective Caml version 3.08.4
# #use "topfind";;
- : unit = ()
Findlib has been successfully loaded. Additional directives:
#require "package";; to load a package
#list;; to list the available packages
#camlp4o;; to load camlp4 (standard syntax)
#camlp4r;; to load camlp4 (revised syntax)
#predicates "p,q,...";; to set these predicates
Topfind.reset();; to force that packages will be reloaded
#thread;; to enable threads
- : unit = ()
# #camlp4o;;
/home/martin/godi/lib/ocaml/std-lib/camlp4: added to search path
/home/martin/godi/lib/ocaml/std-lib/camlp4/camlp4o.cma: loaded
Camlp4 Parsing version 3.08.4
# #require "col";;
/home/martin/godi/lib/ocaml/site-lib/col: added to search path
/home/martin/godi/lib/ocaml/site-lib/col/pa_col.cmo: loaded
/home/martin/godi/lib/ocaml/site-lib/col/run_col.cmo: loaded
# type col point = { x : float; y : float };;
type point = { x : float; y : float; }
module Point :
sig
val create : x:float -> y:float -> unit -> point
val create_tuple : x:float -> y:float -> unit -> float * float
class obj :
x:float ->
y:float ->
unit ->
object
val y : float
val x : float
method x : float
method y : float
end
exception Bad_format
val x_of_string : string -> float
val x_to_string : float -> string
val y_of_string : string -> float
val y_to_string : float -> string
type t = point
module Index : sig val x : int val y : int end
module Compare : sig val x : 'a -> 'a -> int val y : 'a -> 'a -> int end
val fields : string array
val labels : string array
val of_array : string array -> point
val to_array : point -> string array
exception Invalid_field of string
exception Invalid_label of string
val type_float_field : string -> t -> float
val type_float_label : string -> t -> float
val load_csv_rows :
?strict:bool -> ?noheader:bool -> string -> (point -> unit) -> unit
val load_csv :
?strict:bool -> ?noheader:bool -> ?rev:bool -> string -> point list
val open_out_csv :
?sep:char ->
?noheader:bool -> string -> (point -> unit) * (unit -> unit)
val save_csv_rows :
?sep:char -> ?noheader:bool -> string -> (unit -> point option) -> unit
val save_csv :
?sep:char -> ?noheader:bool -> string -> point list -> unit
val compare_fields :
[< `Custom of point -> point -> int | `Down of string | `Up of string ]
list -> point -> point -> int
val compare_labels :
[< `Custom of point -> point -> int | `Down of string | `Up of string ]
list -> point -> point -> int
module Tup :
sig
type t = float * float
val create : x:float -> y:float -> unit -> float * float
val of_array : string array -> float * float
val to_array : float * float -> string array
val of_record : point -> t
val to_record : t -> point
val get_x : t -> float
val get_y : t -> float
exception Invalid_field of string
exception Invalid_label of string
val type_float_field : string -> t -> float
val type_float_label : string -> t -> float
val load_csv_rows :
?strict:bool ->
?noheader:bool -> string -> (float * float -> unit) -> unit
val load_csv :
?strict:bool ->
?noheader:bool -> ?rev:bool -> string -> (float * float) list
val open_out_csv :
?sep:char ->
?noheader:bool ->
string -> (float * float -> unit) * (unit -> unit)
val save_csv_rows :
?sep:char ->
?noheader:bool ->
string -> (unit -> (float * float) option) -> unit
val save_csv :
?sep:char ->
?noheader:bool -> string -> (float * float) list -> unit
val compare_fields :
[< `Custom of t -> t -> int | `Down of string | `Up of string ]
list -> t -> t -> int
val compare_labels :
[< `Custom of t -> t -> int | `Down of string | `Up of string ]
list -> t -> t -> int
end
module OO :
sig
class t : x:float -> y:float -> unit -> obj
val create : x:float -> y:float -> unit -> t
val of_array : string array -> t
val to_array : < x : float; y : float; .. > -> string array
val of_record : point -> t
val to_record : < x : float; y : float; .. > -> point
exception Invalid_field of string
exception Invalid_label of string
val type_float_field : string -> t -> float
val type_float_label : string -> t -> float
val load_csv_rows :
?strict:bool -> ?noheader:bool -> string -> (t -> unit) -> unit
val load_csv :
?strict:bool -> ?noheader:bool -> ?rev:bool -> string -> t list
val open_out_csv :
?sep:char ->
?noheader:bool ->
string -> (< x : float; y : float; .. > -> unit) * (unit -> unit)
val save_csv_rows :
?sep:char ->
?noheader:bool ->
string -> (unit -> < x : float; y : float; .. > option) -> unit
val save_csv :
?sep:char ->
?noheader:bool ->
string -> < x : float; y : float; .. > list -> unit
val compare_fields :
[< `Custom of
(< x : 'b; y : 'c; .. > as 'a) ->
(< x : 'b; y : 'c; .. > as 'd) -> int
| `Down of string
| `Up of string ]
list -> 'a -> 'd -> int
val compare_labels :
[< `Custom of
(< x : 'b; y : 'c; .. > as 'a) ->
(< x : 'b; y : 'c; .. > as 'd) -> int
| `Down of string
| `Up of string ]
list -> 'a -> 'd -> int
end
end
#
Comments (0)
You don't have permission to comment on this page.