more than that. The VBA code was written in a terse, straight-ahead style that
was fairly easy to follow. But somehow
when coding in Java we built up a nest
of classes that left people scratching
their heads when they wanted to understand just what piece of code was
actually being invoked when a given
method was called. Code that made
heavy use of inheritance was particularly difficult to think about, in part because of the way that inheritance ducks
under abstraction boundaries.
In 2005, emboldened by the success of the research group, Jane Street
initiated another rewrite of its core
trading systems, this time in OCaml.
The first prototype was done in three
months, and was up and trading three
months after that. The use of OCaml in
the company has only expanded since
then. Today it is used to solve problems in every part of the company, from
accounting to systems administration,
and that effort continues to grow. In recent years, the trading side of the firm
has increased its use of the language,
and OCaml training is now a standard
part of the curriculum for new trading
hires. Overall, the transition to OCaml
has been a huge success, resulting in
far stronger technology than we could
have achieved otherwise.
˲ ˲ Performance. We found that
OCaml’s performance was on par with
or better than Java’s, and within spit-
ting distance of languages such as C
or C++. In addition to having a high-
quality code generator, OCaml has an
incremental GC (garbage collector).
This means the GC can be tuned to do
small chunks of work at a time, making
it more suitable for soft real-time appli-
figure 1. expression type and evaluator in ocaml.
type ’a expr = | True
| False
| And of ’a expr ’a expr
| Or of ’a expr ’a expr
| Not of ’a expr
| Base of ’a
let rec eval eval_base expr =
let eval’ x = eval eval_base x in
match expr with
| True -> true
| False -> false
| Base base -> eval_base base
| And (x,y) -> eval’ x && eval’ y
| Or (x,y) -> eval’ x || eval’ y
| Not x -> not (eval’ x)
figure 2. expression type and evaluator in Java.
public abstract class Expr<T> {
public interface Evaluator<T> { boolean evaluate(T value); }
public abstract boolean eval(Evaluator<T> evaluator);
Why ocaml?
What is it about the language that
makes it work so well? Here is a short
summary of what I perceive as OCaml’s
key strengths.
˲ ˲ Concision. Our experience with
OCaml on the research side convinced
us that we could build smaller, simpler, easier-to-understand systems in
OCaml than we could in languages
such as Java or C#. For an organization that valued readability, this was a
huge win.
˲ ˲ Bug detection. Programmers who
are new to OCaml are often taken aback
by the degree to which the type system
catches bugs. The impression you
get is that once you manage to get the
typechecker to approve of your code,
there are no bugs left. This isn’t really
true, of course; OCaml’s type system is
helpless against many bugs. There is,
however, a surprisingly wide swath of
bugs against which the type system is
effective, including many bugs that are
quite hard to get at through testing.
public class True<T> extends Expr<T> {
public boolean eval(Evaluator<T> evaluator) { return true; }
}
public class False<T> extends Expr<T> {
public boolean eval(Evaluator<T> evaluator) { return false; }
}
public class Base<T> extends Expr<T> {
public final T value;
public Base(T value) {
this.value = value; }
public boolean eval(Evaluator<T> evaluator)
{ return evaluator.evaluate(value); }
}
public class And<T> extends Expr<T> {
public final Expr<T> expr1;
public final Expr<T> expr2;
public And(Expr<T> expr1, Expr<T> expr2) {
this.expr1 = expr1;
this.expr2 = expr2;
}
public boolean eval(Evaluator<T> evaluator) {
return expr1.eval(evaluator) && expr2.eval(evaluator);
}
}
public class Or<T> extends Expr<T> {
public final Expr<T> expr1;
public final Expr<T> expr2;
public Or(Expr<T> expr1, Expr<T> expr2) {
this.expr1 = expr1;
this.expr2 = expr2;
}
public boolean eval(Evaluator<T> evaluator) {
return expr1.eval(evaluator) || expr2.eval(evaluator);
}
}
public class Not<T> extends Expr<T> {
public final Expr<T> expr;
public Not(Expr<T> expr) { this.expr = expr; }
public boolean eval(Evaluator<T> evaluator)
{ return !expr.eval(evaluator); }
}
}