There's no need to pick! Reason and OCaml share the exact same semantics (i.e. how the code runs). Only the syntax differ. Carry Reason-tools around so that you can freely convert between the two syntaxes. A Reason tutorial is an OCaml tutorial, vice-versa. In the terminal, you can have these alises:
# converts ocaml code into reason alias mlre="pbpaste | refmt --parse ml --print re --interface false | pbcopy" # converts reason code into ocaml alias reml="pbpaste | refmt --parse re --print ml --interface false | pbcopy"
They'll take your code from the (macOS) clipboard, convert it, and paste it back into your clipboard! Swap out pbpaste/pbcopy with your system's clipboard functions.
string_of_intfunctions come from?
They're from the standard library, pre-
opened during the compilation of your file. This is why you see them in scope.
Js.log. If you're compiling to native, you'll need something like ppx_show. A future OCaml feature (called modular implicit) will solve this directly in the language.
Most JS libraries should easily work under Reason + BuckleScript. On the native side, since Reason's just a syntax transform: yes, they work with Reason too. But the native workflow is currently work-in-progress and needs polish.
We do compile to native, but the native workflow is currently work-in-progress. At this time, we recommend compiling to JS through BuckleScript and use the bindings at reasonml-community or somewhere else.
First, if you're not interfacing with any library that uses promises, you can simply use callbacks. Everyone gets them and they're performant.
If you need to bind to a JS library that uses promises, or communicate with such library, you can use BS's bindings to promises. There's also potential to have some syntactic sugar in the future. In the long run, we'd like to implement a spec-compliant promises implementation in OCaml/Reason proper, so that the compiler optimizations could kick in.
Some of OCaml's language features (not just types) might be able to defer the need for unit testing until later. In the meantime, for compilation to JS, we're working on Jest bindings. We'll look into using Jest for native too, if Jest is written using Reason in the future (no concrete plan yet). OUnit is a good, small native OCaml testing library right now.
.merlinfile at the root of my project?
bsb the build system generates the
.merlin for you; You don't need to check that into your version control and don't have to manually modify it.
requirein my file; how does module resolution work?
Reason/OCaml doesn't require you to write any import; modules being referred to in the file are automatically searched in the project. Specifically, a module
Hello asks the compiler to look for the file
hello.ml (and their corresponding interface file,
hello.mli, if available).
A module name is the file name, capitalized. It has to be unique per project; this abstracts away the file system and allows you to move files around without changing code.
Not currently. You'd have to do the manual translation. Alternatively, try using JS objects directly
Generally speaking, we recommend binding to the JS library thinly rather than thickly and idiomatically; better stay lightweight and catch conversion mistakes.
See also our JS interop guide.
Not currently. Though you can output JS artifacts alongside your Reason files. See the
in-source option here, in package-specs -> package-spec -> module-format-object.
Are you using a third-party module? If you're compiling to JS, did you add the dependency in your
bs-dependencies field? Also, did you do
bsb by default only build the root project itself for performance.
Additionally, don't forget to add the source folders into your
bsconfig.json! For performance,
bsb doesn't automatically and recursively build nested folders.
Some | None,
Listand all of these special? Where do they come from?
They're ordinary variants/records/module definitions that comes with the standard library,
opened by default during compilation out of convenience.
Say you have
List.map (fun item => 1) myList. The argument
item isn't used and will generate a compiler warning. Using
fun _ => 1 instead indicates that you're intentionally receiving and ignoring the argument, therefore bypassing the warning. Alternatively,
fun _item => 1 has the same effect, but indicates more descriptively what you're ignoring.
MyModule.tI keep seeing?
MyModule is a module's name,
t is a community convention that indicates "the type that represents that module, whatever that means". For example, for the
String.t is the type carried around and representing "a string".
Js_promiseand then a
Js.Promise? What about
Js_stringand whatever else?
As a convention,
Js_foo is the actual module, and
Js.Foo is just an alias for it. They're equivalent. Prefer
Js.Foo, because that's the official, public module name.
They will one day. In the meantime, help us ship more Reason code! The popularity will help funnel more OCaml contributions. The less the OCaml folks need to worry about low-hanging fruits, the more they can focus on great research and execution!
BuckleScript is optimized for performance across the whole stack. You can try slowing it down by adding a dozen layers of indirections and metaprogramming. Try:
.ml: OCaml source file
.mli: OCaml interface file; determines which parts of the matching
.mlfile are visible to the outside world
.re: Reason source file. Like
.ml, but for Reason
.rei: Reason interface file. Like
.mli, but for Reason
.cmi: Compiled interface (.rei/mli) file
.cmx: Compiled object file for native output (via ocamlopt)
.cmo: Compiled object file for bytecode output
.cmj: Compiled object file for web (via BuckleScript)
.cma: Library file for bytecode output (equivalent to C's .a files)
.cmxa: Library file for native output
.cmt: Contains a "Typedtree" – basically the AST with all type info
.cmti: Just like a .cmt file, but for interface files
.cmxs: Dynamically loaded plugin (for native compilation)
.o: Compiled native object file
.out: Conventional name/extension for final output produced by ocamlc/ocamlopt (e.g.
ocamlc -o myExecutable.out)
.mll: ocamllex lexical analyzer definition file
.mly: ocamlyacc parser generator definition file
.mldylib: Contains a list of module paths that will be compiled and archived together to build a corresponding
.cmxstarget (native plugin)
.mliv: Batteries-specific files for some custom preprocessing.
.mllib: Ocaml library (cma and cmxa)
.mlpack: Ocaml package (cmo built with the -pack flag)
.mlpp: Extlib-specific files for some custom preprocessing
.mltop: OCamlbuild top-level file, used by OCamlbuild to generate a .top file
.odocl: OCaml documentation file
If some of those explanations are still a bit cryptic, here are expansions on some of the terms used above:
There is more information and context for many of these file extensions on the OCaml site and in this mailing list post. There are also deeper dives on native and bytecode compilation that contain more detailed descriptions in the OCaml manual.