Home/Tutorials/ReasonML/Reason Functions
ReasonML6 min read

Reason Functions

Reason is a syntax on top of OCAML that was geared towards bringing JavaScript Developers closer to the OCAML tool chain and semantics.

REASON Functions


Functions in reason may look familiar if you are conversant with es6.

Check out the example we had in the previous lesson on getting the newAge


```reason
let newAge = (age) => age + 1;

```

So newAge is a function that takes an int argument and returns the int added to 1.

As you have already seen the code you write gets compiled to JavaScript. For instance if your file was named fn.re then the compiled file will be named fn.bs.js

Functions don’t necessarily need to take any arguments. They can perform an operation by calling other functions within them, functions taking no arguments are said to take unit as the argument. ().


```reason

let resolveDate = () => {
    Js.log("Returning the current date")
    Js.Date.now()
}

```

So this resolveDate function when called prints to the console of the Js environment its running on. (Browser, node etc) and returns the current date

Multiple Arguments

Functions can take multiple arguments.

Eg: lets define a function that takes 2 strings and returns their concatenation.

Say it takes a first name and then a last name and returns a concatenated string of the FullNames.


```reason

let name = (first, last) => first ++ " " ++ last

```

name(“Jane”, “Doe”) gives us Jane Doe

Reason ML functions are automatically curried. In case you are wondering, currying is the process of breaking down a function with multiple arguments into a series of functions that take partial arguments.

For instance, we can call the function above as


```reason

let firstName = name("John")

let fullName = firstName("Doe")

```

If you open the compiled Js file you will notice something.

FirstName is now a function that takes on one argument and returns the named function with John as the first name and the parameter you will pass as the last.


```js
function name(first, last) {
  return first + (" " + last);
}

function firstName(param) {
  return name("John", param);
}

var fullName = firstName("Doe");
```
Output :-

The result of fullName is John Doe.

This is all good , but now we can be confused as to which is the first name and position in which we are to place it in the arguments, each time we forget we would have to lookup the function definition. This can slow us down and an alternative to solving this problem would be to use labeled arguments

We can rewrite the function as


```reason

let name = (~firstname, ~lastname) => firstname ++ " " ++ lastname
```
and then refactor the get name functions as follows.

```reason

let somename = name(~lastname="Doe")

let fullName = somename(~firstname="John")

```

Labeled functions are powerful because the order in which you place to the arguments doesn’t matter.

On peeking to the compiled Js we see:

```js
function name(firstname, lastname) {
  return firstname + (" " + lastname);
}

function somename(param) {
  return name(param, "Doe");
}

var fullName = "John Doe";
```

fullName no longer returns a function call but gives us back a string. A string is less expensive as compared to a function call or a chain of function calls. This is a win for us.

Optional Arguments

Lets say we want to make a function that takes a person’s name and age and returns a string of the name and age, but in this case the age is optional as users can opt not to give their age.


```reason

let toString = (~name, ~age=?, ()) => {
    switch age {
    | None => "The User's name is " ++ name ++ ""
    | Some(agevalue) => "The User's name is " ++ name ++ " and his age is" ++ string_of_int(agevalue)
    };
}

```

What we now have is a combination of 2 powerful concepts, Pattern Matching and Variants.

We shall now talk more about those in upcoming lessons.

In general a variant is a data structure that can represent other data structures. (integers, strings, lists etc).

Recall type arguments, well the None and Some come from an option type, which returns either a None or Some of value provided.


```reason
option('a) = None | Some('a)
```

To bring this into context, if age isn’t provided in the function call age gets matched to None


```reason

let alex = toString(~name="Alex", ())

```

and if age is provided it gets matched to Some(age)


```reason

let george = toString(~name="George", ~age=23, ())

```
Note :

The Unit () is used so as not to bring about confusion when age is not provided. We don’t want the compiler to curry the function as it awaits an argument that will not be provided.


```reason

let alex = toString(~name="Alex")

```

The above instance will curry the function as it awaits the age param. A peek into the Js file and you will see the following.


```js
function alex(param, param$1) {
  return toString("Alex", param, param$1);
}
```

But on providing the Unit the compiler then knows that we have explicitly left out the age parameter.

Refactor the alex let binding back to the original state.


```reason

let alex = toString(~name="Alex", ())

```

and a peek into the Js. You will see the following.


```js
var alex = toString("Alex", undefined, /* () */ 0);
```

Which shows that age has been marked as undefined.

Recursive Functions

Recursive functions are functions that call themselves repeatedly, until a certain condition is met.

Recursive functions have a different signature compared to normal functions. The signature applies to both Ocaml and Reason alike when declaring a recursive function we use the rec keyword.

Let’s define a recursive function that computes the sum of a list’s values.


```reason

let rec sum = lst => {
    switch lst {
    | [] => 0
    | [hd, ...tl] => hd + sum(tl)
    };
}

```

Again we are met with pattern matching which we will discuss broadly in upcoming lessons.s

So if the list is empty we return 0, but if the list is not empty we add the head to the recursive call of the same function with the tail of the list.

Note :
  1. Head of a list is the first element.
  2. Tail of a list is the list minus the head.
  3. Whenever you want to make a function recursive always include the rec keyword.

```reason

let a = sum([1,2,3,4])

```

With this a will equal 10.

In the next lesson, we will look at variants and how we can use them.


INTERACTIVE SIMULATION CHALLENGE+250 XP
Workbench Verification

Ready to test "Reason Functions" in production?

See how ReasonML algorithms and server loops perform under 100k req/s traffic spikes.

Simulator: SysDesign Ops Simulator