Reference card¶
Everything the subset has, on one page.
Three of these tables are generated
The operators, the keywords and the standard library are read off the compiler itself when this page is built, so they cannot fall behind it. The prose around them is written by hand.
Definitions¶
let x = 42
let f x y = x + y (* two parameters *)
let rec fact n = (* rec, for a recursive call *)
if n <= 1 then 1 else n * fact (n - 1)
let rec even n = ... and odd n = ... (* mutual recursion *)
let () = print_int (fact 5) (* run something *)
let a, b = 1, 2 (* a pattern binds *)
let g x = let y = x * 2 in y + 1 (* local, with `in` *)
Types¶
int float char string bool unit exn
'a list 'a array 'a option 'a ref
int * string (* a pair *)
int -> int -> int (* a function of two arguments *)
type colour = Red | Green | Blue
type 'a tree = Empty | Node of 'a tree * 'a * 'a tree
type point = { x : float; mutable y : float }
type number = int (* an alias *)
exception Empty
exception Too_big of int
A constructor takes one argument, and of int * string makes that argument a pair. mutable is what lets a field be assigned with <-.
Expressions¶
if c then a else b (* both branches, same type *)
match e with | p -> a | q when g -> b
function | p -> a | q -> b (* a function that matches *)
fun x y -> e (* anonymous *)
try e with Empty -> a | Failure m -> b
while c do e done
for i = 0 to n - 1 do e done (* `downto` counts back *)
a; b (* a is evaluated for its effect *)
begin a; b end (* the same, bracketed *)
[ 1; 2; 3 ] 1 :: rest l1 @ l2
[| 1; 2; 3 |] t.(i) t.(i) <- v
s.[i] "bon" ^ "jour"
{ x = 1.0; y = 2.0 } p.x p.y <- 3.0 { p with x = 0.0 }
let r = ref 0 in r := !r + 1; incr r
Patterns¶
_ x 42 'a' "s"
(a, b) a :: rest [] [ a; b ] [| a; b |]
Node (l, v, r) Some x None
{ x = a; y = b } p as whole 0 | 1 | 2
Every alternative of a | pattern has to bind the same names, and a case may carry a guard: | n when n < 0 -> ....
Operators¶
Tightest first. Application binds tighter than any of them, and prefix -, -. and ! tighter still.
| level | operators | associates |
|---|---|---|
| 1 | ** lsl lsr asr |
right |
| 2 | * / *. /. mod land lor lxor |
left |
| 3 | + - +. -. |
left |
| 4 | :: |
right |
| 5 | @ ^ |
right |
| 6 | = <> < <= > >= |
left |
| 7 | && |
right |
| 8 | \|\| |
right |
The . forms are for floats: 1 + 2 and 1.0 +. 2.0, and never the two mixed. = is structural equality, <> its negation, and := writes through a ref. Any of them can be used as a value by bracketing it, as in List.fold_left ( + ) 0.
Keywords¶
and as asr begin do done downto else end exception false for fun function if in land let lor lsl lsr lxor match mod mutable of rec then to true try type when while with
The standard library¶
Everything a programme may use without defining it, with the type it has. There is no open: a module name is a prefix.
Always in scope¶
| name | type |
|---|---|
not |
bool -> bool |
ref |
'a -> 'a ref |
incr |
int ref -> unit |
decr |
int ref -> unit |
ignore |
'a -> unit |
fst |
'a * 'b -> 'a |
snd |
'a * 'b -> 'b |
compare |
'a -> 'a -> int |
min |
'a -> 'a -> 'a |
max |
'a -> 'a -> 'a |
abs |
int -> int |
succ |
int -> int |
pred |
int -> int |
raise |
exn -> 'a |
failwith |
string -> 'a |
invalid_arg |
string -> 'a |
print_int |
int -> unit |
print_float |
float -> unit |
print_char |
char -> unit |
print_string |
string -> unit |
print_endline |
string -> unit |
print_newline |
unit -> unit |
read_int |
unit -> int |
read_float |
unit -> float |
read_line |
unit -> string |
string_of_int |
int -> string |
int_of_string |
string -> int |
string_of_float |
float -> string |
float_of_string |
string -> float |
string_of_bool |
bool -> string |
bool_of_string |
string -> bool |
float_of_int |
int -> float |
int_of_float |
float -> int |
char_of_int |
int -> char |
int_of_char |
char -> int |
truncate |
float -> int |
sqrt |
float -> float |
exp |
float -> float |
log |
float -> float |
sin |
float -> float |
cos |
float -> float |
tan |
float -> float |
atan |
float -> float |
floor |
float -> float |
ceil |
float -> float |
abs_float |
float -> float |
+ |
int -> int -> int |
- |
int -> int -> int |
* |
int -> int -> int |
/ |
int -> int -> int |
mod |
int -> int -> int |
land |
int -> int -> int |
lor |
int -> int -> int |
lxor |
int -> int -> int |
lsl |
int -> int -> int |
lsr |
int -> int -> int |
asr |
int -> int -> int |
+. |
float -> float -> float |
-. |
float -> float -> float |
*. |
float -> float -> float |
/. |
float -> float -> float |
** |
float -> float -> float |
^ |
string -> string -> string |
@ |
'a list -> 'a list -> 'a list |
= |
'a -> 'a -> bool |
<> |
'a -> 'a -> bool |
< |
'a -> 'a -> bool |
<= |
'a -> 'a -> bool |
> |
'a -> 'a -> bool |
>= |
'a -> 'a -> bool |
&& |
bool -> bool -> bool |
\|\| |
bool -> bool -> bool |
:= |
'a ref -> 'a -> unit |
! |
'a ref -> 'a |
List¶
| name | type |
|---|---|
List.length |
'a list -> int |
List.hd |
'a list -> 'a |
List.tl |
'a list -> 'a list |
List.nth |
'a list -> int -> 'a |
List.rev |
'a list -> 'a list |
List.append |
'a list -> 'a list -> 'a list |
List.concat |
'a list list -> 'a list |
List.map |
('a -> 'b) -> 'a list -> 'b list |
List.rev_map |
('a -> 'b) -> 'a list -> 'b list |
List.mapi |
(int -> 'a -> 'b) -> 'a list -> 'b list |
List.iter |
('a -> unit) -> 'a list -> unit |
List.iteri |
(int -> 'a -> unit) -> 'a list -> unit |
List.fold_left |
('a -> 'b -> 'a) -> 'a -> 'b list -> 'a |
List.fold_right |
('a -> 'b -> 'b) -> 'a list -> 'b -> 'b |
List.filter |
('a -> bool) -> 'a list -> 'a list |
List.exists |
('a -> bool) -> 'a list -> bool |
List.for_all |
('a -> bool) -> 'a list -> bool |
List.mem |
'a -> 'a list -> bool |
List.assoc |
'a -> ('a * 'b) list -> 'b |
List.split |
('a * 'b) list -> 'a list * 'b list |
List.combine |
'a list -> 'b list -> ('a * 'b) list |
List.sort |
('a -> 'a -> int) -> 'a list -> 'a list |
List.init |
int -> (int -> 'a) -> 'a list |
Array¶
| name | type |
|---|---|
Array.length |
'a array -> int |
Array.make |
int -> 'a -> 'a array |
Array.init |
int -> (int -> 'a) -> 'a array |
Array.make_matrix |
int -> int -> 'a -> 'a array array |
Array.get |
'a array -> int -> 'a |
Array.set |
'a array -> int -> 'a -> unit |
Array.copy |
'a array -> 'a array |
Array.sub |
'a array -> int -> int -> 'a array |
Array.append |
'a array -> 'a array -> 'a array |
Array.of_list |
'a list -> 'a array |
Array.to_list |
'a array -> 'a list |
Array.iter |
('a -> unit) -> 'a array -> unit |
Array.iteri |
(int -> 'a -> unit) -> 'a array -> unit |
Array.map |
('a -> 'b) -> 'a array -> 'b array |
Array.fold_left |
('a -> 'b -> 'a) -> 'a -> 'b array -> 'a |
Array.sort |
('a -> 'a -> int) -> 'a array -> unit |
Array.blit |
'a array -> int -> 'a array -> int -> int -> unit |
Array.fill |
'a array -> int -> int -> 'a -> unit |
String¶
| name | type |
|---|---|
String.length |
string -> int |
String.get |
string -> int -> char |
String.sub |
string -> int -> int -> string |
String.concat |
string -> string list -> string |
String.make |
int -> char -> string |
String.init |
int -> (int -> char) -> string |
String.index |
string -> char -> int |
String.contains |
string -> char -> bool |
String.uppercase_ascii |
string -> string |
String.lowercase_ascii |
string -> string |
String.split_on_char |
char -> string -> string list |
String.compare |
string -> string -> int |
Char¶
| name | type |
|---|---|
Char.code |
char -> int |
Char.chr |
int -> char |
Char.lowercase_ascii |
char -> char |
Char.uppercase_ascii |
char -> char |
Deliberate differences from OCaml¶
| here | real OCaml | |
|---|---|---|
int |
unbounded | 63-bit, and it wraps |
| argument order | left to right | unspecified |
< and friends |
int, float, char, string |
any type |
| tail calls | use stack | use none |
== and != |
absent | physical equality |
exhaustiveness of match |
not checked | a warning |
| a string inside a comment | not scanned | scanned |
Each of those is a decision with a way out, listed in SPEC.md in the repository.
Not in the subset¶
Modules, functors, objects, classes, GADTs, polymorphic variants, labelled and optional arguments, first-class modules, lazy, assert, and user-defined operators.
Printf and Hashtbl are the two most missed, and are the first two planned. Printf is awkward because OCaml gives format strings a type that plain Hindley-Milner cannot infer; Hashtbl needs one more parametric abstract type and nothing else.