Using the playground¶
Open it, then come back here when something is puzzling.
Type a programme on the left and press Ctrl or ⌘ + Enter, or click Run. The Programme dropdown loads any of the eighteen worked examples, each of which runs as it stands.
Everything happens in your browser. Nothing is uploaded, nothing is stored, and there is no OCaml on the far end: the compiler is written in Python, and Python is running in your tab.
The five views¶
Run¶
What the programme prints.
A programme with no let () = ... prints nothing, and that is fine: half the examples only define functions. If you want to see something, add a line:
The status line, top right, says both back ends agree when it went well.
Your programme is executed twice. Once by walking the syntax tree, and once by compiling it to Python and running that. Two independent back ends, one shared runtime, and the line reports whether they printed the same thing. This is the project's own correctness test, running on whatever you typed. It has caught real defects; see running it, twice.
Types¶
The signature the compiler inferred, in the form the real ocamlc -i prints. Nothing in your source says what type anything is; all of it was worked out.
A type variable written '_weak1 has not been generalized, and that is not a bug. Try it:
You get '_weak1 list ref, not 'a list ref. If it were 'a, the same cell could be filled with an int in one place and read back as a string in another, and the type system would be lying to you. Refusing to generalize is called the value restriction, and real OCaml does exactly the same.
Names¶
The scope tree, one per namespace. This is the view no other OCaml playground has.
Each block shows what it binds:
| block | what it is |
|---|---|
module top |
the whole file |
binding |
a function's parameters |
case |
one arm of a match |
fun |
an anonymous function's parameters |
let |
the body of a let ... in |
for |
a loop's index |
Reading it answers the questions people actually get stuck on. Which x does this x refer to? Does this recursive call resolve? Does that parameter escape the function? The tree says so, without you having to reason it out.
There are five trees, because OCaml keeps five kinds of name apart: values, constructors, record fields, type names and type variables. A record label x and a variable x are unrelated names in OCaml, so they are in different trees. Constructors and exceptions share one, because OCaml shares it.
Anything the compiler could not find is listed above the trees.
Python¶
What the second back end emits. It is meant to be readable: let f x y = ... becomes def f(x, y) and a call with both arguments becomes a direct call.
Where you see _rt.BINARY_OPS['/'] in place of a plain /, the two languages disagree. OCaml's integer division truncates towards zero and Python's rounds down, so (-7) / 2 is -3 in OCaml and -4 in Python. = is structural equality, which is not Python's == either. Where they agree, the operator is emitted directly, which is why the arithmetic mostly reads normally.
Names get freshened, so a shadowing let x = ... comes out as x_2. That is what keeps an earlier closure reading the x it captured.
Printed¶
Your source, printed back out of the tree the compiler built. It is how you check that it read what you meant: if a bracket appears that you did not type, the grouping was not what you thought.
Try 1 + 2 * 3 and then 1 + 2 :: l @ m, and see where the brackets land.
Sharing¶
Copy link puts your whole programme into the URL, after #code=, and copies it. Anybody opening that link sees your code.
Nothing is stored anywhere; the programme travels in the link itself, so a very long programme makes a very long link.
When something goes wrong¶
Problems appear in a red band above the views, prefixed by the stage that found them.
syntax: 3:14: expected … found …- The parser stopped at line 3, column 14, and lists everything that could have come next. Usually a missing
in, a missing->, or a,where a;was wanted. names: 'foo' is not declared in vals- A name nothing defines. Check the spelling, and check that the
letdefining it comes earlier in the file: order matters at the top level. types: TypingError: this has type … but … was expected- Two types had to be the same and were not. The commonest cause by a distance is mixing
intandfloat: OCaml has+and+.and they are different operators. interpreter: OCamlError: …- The programme raised an exception nothing caught, exactly as the real
ocamlwould end.
A stage that fails does not stop the others. A programme that does not type still runs, and still shows its scopes. That is often the fastest way to find out what went wrong: look at Names to see what the compiler thinks is in scope.
What is not here¶
There is no editor. Nothing completes your code, colours it, or underlines your mistakes: it is a text box and five answers.
Printf and Hashtbl are missing, and so are modules of your own, objects and functors. The reference card lists what there is.
Long-running programmes freeze the tab, because everything runs on one thread. Reload the page to stop one.