Date module in your OCaml code.
It’s better to have some knowledge of OCaml, and we have written extensively about it, but it’s also easy enough to get the gist of the benefits from our simple examples.
BuckleScript vs js_of_ocaml
js_of_ocaml takes low-level bytecode from OCaml compiler, BuckleScript takes the high-level rawlambda representation from OCaml compiler
js_of_ocaml focuses more on existing OCaml ecosystem(opam) while BuckleScript’s major goal is to target npm
js_of_ocaml is for OCaml developers to be able to run their code in the browser.
BuckleScript vs ReasonML
ReasonML is often mentioned together with BuckleScript, which makes it a bit confusing to understand their differences at first.
Compared do OCaml, ReasonML has a friendlier syntax (for people coming from JS) and better support for JSX (inline XML tags). The difference in syntax is significant that we are really talking about some dialect of OCaml.
BuckleScript vs TypeScript
In , Hongbo provides a comparison between the two systems. Some of the pros and cons raised are:
- Designed for JS, easy inter-operate with JS
- Compiler slow (not scalable for FB/Google scale)
- Verbose, very limited type inference
- Start up time slow (very hard to build traditional build tools)
- Types are only used for tooling – soundness is not the design goal, not very reliable
- No code optimizations
- Compiles much faster, scales better
- Sound type system, global type inference
- Types are used in code optimization, optimizing compiler
- Learning curve is higher compared with TypeScript
The easiest way to try out examples is through this BuckleScript playground.
To try it locally, we can follow . It generates an initial bsconfig.json file and the compilation process can be done via npm. The process involve converting a OCaml file (
.bs.js). The latter should be included in your application, but both should be considered part of your codebase and hence committed.
How to print to stdout using BucketScript? The most basic program is simply printing a Hello World. In OCaml we would do “Print.printf” to print to stdout, but OCaml modules are not readily available for BuckleScript. We can use the
Js.log() function for this purpose:
This maps to:
Looping over an Array
We can use an imperative-style code in OCaml:
[| 10; 20; 30 |]. If we generate this code we get:
The interesting thing here is that we do have access to some basic OCaml libraries, for example
Which maps to
Looping over a List
List. What happens if we use
We simply dropped the | to use a
List instead of
Array and now we can use the more standard fold_left instead of reduce. This translates to:
This is very interesting! We studied functional data structures OCaml extensively in the past and the key concept is that by default data structures are persistent. If we look closely what is being passed to
sum(), we see it’s a linked-list like structure:
[10, [20, [30, 0]]], the 0 being used to indicate the end.
which maps to:
MyModule. To me it would make more sense to export them as Object.
A nice feature from functional languages is the concept of currying, which allow us to perform partial application of functions. For example, if we have a function that adds two numbers, we can derive an increment function that partially applies sum by binding the first value to 1:
bind(), but the syntax is not as neat:
Another neat syntax from OCaml is the chaining operator. One can chain functions via the
|> operator: the result of the lefthand function is passed as argument to the righthand function.
A common use for this is when we want to apply a series of function in sequence without assigning to a variable.
An alternative would be to nest the calls so we don’t have to repeat the variable, but that would hurt legibility. In OCaml, we could chain these calls:
We could do:
Here, the OCaml code is more verbose but we provided a stronger contract by typing the function
readFile(). The syntax for importing modules is
is the same as
, the latter can be omitted.
Objects as Maps
Objects as Records
To represent an Object as a record, we can use a OCaml record type syntax:
We added the
[@bs.optional] to indicate that a field is optional. We also added the
[@@bs.deriving abstract] attribute to indicate it should not be directly instantiated like
Instead, it generates a “constructor” function. In the same way, the properties of a record are not directly available. They also need to go through intermediate auto-generated accessors:
The benefits being stated, there are two main potential drawbacks of using BuckleScript.
Mixed languages. Adopting BuckleScript will cause the codebase to have a mix of different languages, which makes it harder for new developers to ramp up. Of course this can be mitigated by converting the entire codebase to use OCaml.
Through these examples, we saw the OCaml type system in use, as well as some neat syntax and immutable data structures, which can lead to more readable, succinct and reliable code.
 BuckleScript Examples
 BuckleScript playground
 BuckleScript/bucklescript – Comparisons
 BuckleScript – New Project