Maintainer: Mike Lin
"The Whitespace Thing" for OCaml is a preprocessor (invoked as ocaml+twt
) that
uses indentation to auto-parenthesize multi-line expressions, like in Python and
Haskell. Using natural indentation patterns, it eliminates:
;
operator for statement sequences and the ;;
top-level statement operatorin
, done
, begin
, and end
The language syntax is otherwise the same as OCaml's, with a few restrictions.
Version 1 is implemented as a line-oriented preprocessor; this is something of a hack. At some unspecified time in the future, it should be rewritten with a proper syntax tree parser, although the current approach honestly gets quite far!
ocaml | ocaml+twt |
let rec main magic_number = Printf.printf "Your guess? "; let guess = int_of_string (read_line ()) in if guess > magic_number then (Printf.printf "Too high!\n"; main magic_number) else if guess < magic_number then (Printf.printf "Too low!\n"; main magic_number) else (Printf.printf "You win!\n"; exit 0);; Random.self_init ();; main (Random.int 100);; |
let rec main magic_number = Printf.printf "Your guess? " let guess = int_of_string (read_line ()) if guess > magic_number then Printf.printf "Too high!\n" main magic_number else if guess < magic_number then Printf.printf "Too low!\n" main magic_number else Printf.printf "You win!\n" exit 0 Random.self_init () main (Random.int 100) |
let list_out lst = (List.map (function Some x -> x) (List.filter (function Some x -> true | None -> false) lst)) |
let list_out lst = List.map function Some x -> x List.filter function Some x -> true | None -> false lst |
for i = 1 to 10 do print_int i; print_newline () done; print_string "done" |
for i = 1 to 10 do print_int i print_newline () print_string "done" |
let contrived = function s when (String.length s) > 0 -> begin try Some (float_of_string s) with Failure _ -> Some nan end | _ -> None |
let contrived = function | s when (String.length s) > 0 -> try Some (float_of_string s) with | Failure _ -> Some nan | _ -> None |
See the quick reference, and the longer examples/.
ocaml+twt is available in OPAM:
opam install ocaml+twt
. Once installed, the ocaml+twt executable is
available in your path when you eval $(opam config env)
.
Without OPAM, extract the source tarball and make install
. This installs
the executable to PREFIX/bin
where PREFIX=/usr/local
. You can override
this with make install PREFIX=/home/alice
To use the preprocessor, either manually invoke it using ocaml+twt mycode.ml
and pipe the results to a file, or use the preprocessor flag to ocamlc:
ocamlc -pp ocaml+twt mycode.ml
There are a few optional behaviors available for the preprocessor. They're pretty self-explanatory by looking at the usage printed by invoking ocaml+twt.
With ocamlbuild, you can just add something like this to the _tags
file in
your project directory:
<**/*.ml> or <**/*.mli>: pp(ocaml+twt)
If you use OCamlMakefile, you can make the first line of your file
(*pp ocaml+twt *)
.
instead of... | do... |
match n with | 1 -> print_string "one" print_endline () |
match n with | 1 -> print_string "one" print_endline () |
Of course, if the consequent is just a single expression, you can place it on the same line. This restriction is actually true almost everywhere, such as let bodies and if-then consequents; see the quick reference. The rule of thumb: if an expression spans multiple lines, it must begin on its own line.
instead of... | do... |
if b then (+) else (-) x y |
(if b then (+) else (-)) x y |
function | x when x >= 0 -> (+) | _ -> (-) x y |
(function | x when x >= 0 -> (+) | _ -> (-)) x y |
Because the -pp flag to ocamlc is somewhat limited, I included a 'ppcompose' utility that makes it simple to compose several preprocessors. For example, one can compose a list comprehension camlp4 syntax with ocaml+twt as follows:
ocamlc -pp "ppcompose 'camlp4o pa_compr.cmo' 'ocaml+twt -spaceonly'" source.ml
The last preprocessor specified on the command line is applied first to the source code. This means you usually want to put ocaml+twt last.
7/5/15 version 0.94.0
10/05/13 version 0.93.2
10/24/12 version 0.931
02/01/12 version 0.93
08/02/10 version 0.92
03/11/08 version 0.91
01/16/07 version 0.90
12/10/06 version 0.86
07/24/06 version 0.85
02/19/06 version 0.81
11/21/05 version 0.8