In this tutorial / quick-start / notes, I'm going to be exploring Reason. So why not Elm or PureScript? Both languages are super cool but both have some parts I'm not as excited about. PureScript uses Bower -- ew! And neither have easy interoperability with external JavaScript libraries. I had a conversation with @chenglou and he absolutely sold me on Reason. So here goes nothing!
If you're getting started from absolutely nothing on a Mac, the following will get you set up. But it's likely you've already done this:
# install developer tools
xcode-select --install
# install homebrew
/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
# install node and npm
brew install node
# install atom editor
brew cask install atom
These are the necessary tools that are specific to Reason that you probably don't have yet:
# install ninja
brew install ninja
# install and build the reason cli tools
npm install -g git://github.com/reasonml/reason-cli.git
# install the atom editor plugin along with a bunch of other facebook tooling
apm install nuclide
Nuclide is going to mess with your Atom UI so you can go to Settings > Packages
, search for "nuclide" and change the Nuclide Settings. I would try to leave as much there as possible -- you don't want to get stuck on this part trying to get your IDE to work. But if you must, somewhere towards the middle is a "Use" section with a bunch of check boxes. I believe you can turn everything off except for the following:
hyperclick
nuclide-code-format
nuclide-datatip
nuclide-definition-hyperclick
nuclide-language-reason
nuclide-ocaml
nuclide-type-hint
A few customizations I would recommend:
- go to the
nuclide-code-format
section and tick "format on save". - go to the
hyperclick
section and change the the command tocontrol-click
so you can still use command-click for multiple cursors.
At the end of the day, there are 4 editor features that you should make sure are working:
- When you type some garbage syntax, there should be red lines with compile errors.
- When you hover over a variable (where you cursor isn't), a datatip shows up with the type signature of that variable.
- When you control-click on a variable, it will jump to the definition of that variable.
- When you change the whitespace in the file and hit save, everything reformats to the way it was before.
You might notice some errors in the editor already even with a fresh project. That's because the editor tools depend on the artifacts generated by the build system. So let's get this project running:
npm install
npm start
# in another tab
npm run build
# in another tab
open src/index.html
This build system is actually two separate tools. We're using bucklescript
to compile Reason => OCaml => JavaScript, and we're using webpack
to bundle all the files together for the browser.
Reading through the docs is an invaluable experience:
- Reason documentation
- Read the modules section twice!
- Read the JavaScript comparison section as well.
- Rehydrate documentation (for using React with Reason)
- BuckleScript Readme and the BuckleScript documentation (for JS interop)
- OCaml docs (for some of the core function like
sin
andcos
)
Check out the src/tutorial.re
. I've built up a few different examples that you can check out in your browser.
Here are some other places you can find some examples:
-
What's the difference between an abstract type, a polymorphic type, and a generic type?
-
What are the
unit
and_
types called? What are they used for? -
Leveraging the syntax for fun an profit.
I need a function that gets the first
n
items off of a list. My first shot looked like this:let rec firstN n l => if (n === 0 || List.length l === 0) { [] } else { let h = List.hd l; let t = List.tl l; List.append [h] (firstN (n - 1) t) };
But we can do a lot better. We can pattern match on
n
andl
, destructure thehd
andtl
, and spread into a list rather than usingappend
:let rec firstN n l => switch (n, l) { | (0, _) => [] | (_, []) => [] | (n, [h, ...t]) => [h, ...firstN (n - 1) t] };
-
[%bs.debugger]
compiles todebugger
in the browser. You won't see the source mapped back to Reason, but the JavaScript is actually very readable!
-
What if
instanceVars
weren't mutable but were instead returned from the updater methods along with the state? Maybe call it areturnBag
. -
It seems like
memoizedUpdaterCount
is unused since you're usingmaxMemoizedCount
when we make the array. -
Where can I read about
Obj.magic
,Js.Null.return
? -
Can I somehow use Webpack's
import()
for code splitting and async module loading? -
How should I handle compiled assets? I have markdown files that I want to parse at compile-time to generate React components. Should I just use a Makefile to generate
.re
files that are.gitignore
'd? Or are there any compile-time facilities? -
How does publishing Reason packages work?
-
Can I use native OCaml libraries? Where are they? How can I use them? Will they compile to JavaScript? How can I build a native server that doesn't compile to JavaScript?
-
How can I write some simple unit test?