This is a ppx extension which adds
match#const constructs to
OCaml. They behave like normal
match, but conditions are evaluated
at compile time and AST sections not selected are excluded from the program
completely. In conjunction with ppx_getenv, this can be used for conditional
compilation of code.
Published: 20 Nov 2020
This is an OCaml language extension implementing
match%const statements. The
match%const are evaluated at compile time, and the appropriate clause substituted without the ignored clause(s) being fully compiled. This allows you to avoid consequences such as module inclusion or type inference changes which would otherwise have resulted from the ignored clause(s).
In other words, ppx_const works like
#if in the C preprocessor, but is implemented entirely within the OCaml language using the ppx mechanism. In conjunction with ppx_getenv, this provides a lightweight alternative to Cppo.
This software was written by Andi McClure <firstname.lastname@example.org>, based on whitequark's ppx_getenv sample. Significant upgrades were contributed by Kate Deplaix.
Because ppx_const is based on ppx, it requires OCaml 4.02 or newer.
ppx_const may be invoked with either
if%const may be invoked with either of:
if%const COND then A else B if%const COND then A
COND must be one of the following:
An expression consisting of two literals (strings, ints, floats) and either the
COND may also contain extension nodes (including
if%consts) as long as they evaluate to a constant expression by the time ppx_const sees them.
A and B are not required to be of the same type. Like with normal
if, the return type of
if%const false then X is unit.
ppx_const can also be invoked with the following:
match%const MATCHED with P\_1 -> E\_1 | ... | P\_n -> E\_n
MATCHED and P_1..P_n must be either literals (strings, ints, floats) or one of the special constructors
false. Like with
if%const, MATCHED may contain extension nodes, although the P1..P_n may not.
The patterns P_1..P_n may also be variables or
_, in which case they will always match. Matching on a variable name will "bind" a variable by that name in the match expression: If a pattern P_i is a variable
x then the expression, if matched, will compile to
let x = MATCHED in E_i.
An example: Using ppx_const with ppx_gentenv
Say your program has a Graph module with heavyweight dependencies (cairo or whatever). Some users may prefer to compile your program without the graph feature, so that they don't have to install the dependencies. You can do this by installing ppx_const and ppx_getenv, and invoking the graph feature like this:
if%const [%getenv "BUILD_OMIT_GRAPH"] = "" then Graph.create filename else print_endline "Graph feature not available."
In this example, when you build, if the
BUILD_OMIT_GRAPH environment variable is set to a nonempty string then the
Graph.create call will be omitted entirely from the compiled binary. If this is the only invocation of Graph, then the Graph module and all its dependencies will also be omitted from the binary. If you do not set this environment variable, the
[%getenv check will become an empty string at build time and the graph function will be included.
OCamlbuild users take note: For this example to work, you'll need to make certain that ppx_getenv runs before ppx_const, so that
if%const sees a constant string and not the
[% node. If you are using Dune, then Dune will take care of this for you. In OCamlbuild, you set a load order by ordering the packages like this in your
<*>: package(ppx_getenv, ppx_const)
Creative Commons Zero ("public domain or equivalent")