Hello and welcome back to your tutorial series on Reason ML. Yesterday we got familiar with what ReasonML is, what it has to offer, and how to get it installed and configured on our systems and code editors. We also learned about the ReasonML ecosystem and how to get the most out of working experience with the language.

Now it's time to put our focus on learning the core fundamentals of ReasonML. This shouldn't be too bad because if you are coming from a background in Javascript or OCaml, you will find plenty of things to be familiar with along with some new concepts which will be introduced gently.

Diving into the Fundamentals.

First we're going to take a look at the let binding. Let's open up our text editor and write some quick example code.

let a = 1;
let b = "hello world";


So it would be understandable to look at this and think "isn't this just a variable?" While understandable, that wouldn't be 100% accurate. The reason being is that these bindings are immutable. In ReasonML, let bindings are block scoped and immutable values that do bring one unique caveat. To give some resemblance to normal variables for those coming from imperative languages, ReasonML provides what we called shadow variables which means you can do this...

let a = 1;
let b = "hello world";
let a = "wait, I thought this was immutable?"


So what gives? What ReasonML has done is that it has changed the value to which a refers to at this given point in time. So the original value that was assigned to a at the beginning was never changed, it is still there and any functions or data structures that refer to that specific value will be unaffected. However, anything written that is coming after the new a value will now reference the new value created. Unusual? Sure, but it is the compromise that ReasonML offers for its use of the immutable values.

Now, you may be thinking "hey, I thought you said this is a statically typed language? Are you lying to me? Because that is not statically typed right there." And aside from the lying part, you would be somewhat right. However, let's adjust this code a bit to see what ReasonML is up to.

let a: int = 1;
let b: string = "hello world";
let c: float = 2.04;


So now you can see we have actually declared our data types. It's key to understand that ReasonML does offer some degree of type inference, however it is advised that we be specific about our types as often as possible to ensure safe and stable code. However, we aren't only limited to ReasonML's data types. Let's declare one of our own.

type stringData = string;
type person = (string, int);

let a: int = 1;
let b: stringData = "hello world";
let c: float = 2.04;
let d: person = ("Jane", 24);


So now we have StringData which is just our renaming for the string data type. We also have Person which is a tuple with a string and an int in this specific order. As you will see later, this ability to name our own data types can really open some doors as we move forward.

Now let's take a moment and learn a bit about strings and chars in ReasonML. Let's put some code out right quick to illustrate the points that will be made.

let myString: string = "Hello, I am a string.";
let myChar: char = 'a';
let myMultiLineString = {| Hello
world! |};

There isn't anything too mystical to be aware of here. Strings are only allowed to be defined with double quotes. Chars (single letter characters) are defined with single quotes. Then we have multi line strings which are defined with the bracket and pipe symbol. Not bad at all.

Now it is also worth taking note of how booleans work in ReasonML. If you have programmed in most any mainstream programming language then there is nothing to see here. The logical symbols are all the same from what you have worked with in the past. If you know them in Javascript or Ruby or Python or OCaml, it's all the same. This isn't Erlang. So let's move forward.

It's time to discuss integers and floats in Reason as well. It's worth noting that if you are coming from a Javascript background, all numbers default to float. However, in Reason, we have the choice between int and floating point numbers to do our work with. For those who aren't as familiar with the difference between an int and a float, just pause the video on the example I am about to show.

integers: 1, 2, 10, 12423523
floats: 1.0, 2.45, 234575.96845

Having that out of the way. The only real gotcha with ReasonML is that if you are doing operations with floating point numbers, your operator symbols will be slightly different than usual. Let's see it in code.

/* int */
let addint = 1 + 1;
let subint = 2 - 1;
let multiplyint = 2 * 2;
let divideint = 2 / 2;

let addfloat = 1.0 +. 1.4;
let subfloat = 2.0 -. 0.5;
let multiplyfloat = 3.0 *. 2.3;
let dividefloat = 12.4 /. 3.6;

That's really it, you just add a decimal after your normal operator. I know some folks may think this is odd but the ReasonML developers had their rationale for this that they do discuss on their website.

Lastly, we need to go over tuples. You may remember us declaring that Person data type earlier and thinking "wait, what did you just do?" Well now you're about to get the answer to that question. But first, let's get some fresh code to illustrate this with.

let cat = ("orange", "Pixel");
let dog = ("Great Dane", "Bouncer");

So what exactly are these tuples and what do they bring to the table? Well, they are immutable, ordered, and fixed size data structures that can contain different values that will be paired together. That's really it. They are primarily useful when you need to return two paired values together for whatever you are working on. Easy.


Good job, we have now managed to get through the first phase our learning the ReasonML fundamentals. Tomorrow, we will pick up by diving into some of the data structures it offers along with how functions working in this language (hint, it's similar to Javascript).