Because, Reason

ReasonML is not new language. It is described just as new syntax and toolchain.
It’s new syntax (tailored toward JS developers) on top of OCaml language. It compiles to Javascript thanks to Bucklescript compiler. BuckleScript is mostly a compiler, but it does ship some libraries for users’ convenience (Js, Belt, Node, Dom). You can also compile Reason to native Android or iOS. There is also ReasonReact for building React apps with Reason.

Following are some info about creating ReasonReact version of Hoolooskop.

To make our app, we first defined few data types. Sign is a record, question is tuple of strings which makes questions array of tuples.

type sign = {

classname: string,

name: string,

whom: string,

desc: string,

};

type question = (string, string);

type questions = array(question);

All types as well as data are stored in separate Data.re file. Our application is in App.re file and we can use data from Data.re file (like Data.questions) without having to import anything, thanks to Reason first-class files (modules).

Whole application is inside one ReasonReact component and its pretty simple. We have initial state with ‘answers’ array, and ‘opacity’ boolean for UI state. We define state type and initial state data


type state = {

answers: array(int),

opacity: bool

},

InitialState: () => {

answers: [||],

opacity: true

},

we have reducer which add answer to our state array and switch opacity to false


reducer: (action, state) =>

switch (action) {

| SetAnswer(v) =>

ReasonReact.UpdateWithSideEffects(

{answers: Array.append(state.answers, [|v|]), opacity: false},

(

self =>

ignore(Js.Global.setTimeout(() => self.send(FadeButtons), 50))

),

)

| FadeButtons => ReasonReact.Update({...state, opacity: true})

},

Actions are defined as variants type:


type action =

| SetAnswer(int)

| FadeButtons;

Since every question have binary choice our action payload is just one or zero, from

<button> self.send(SetAnswer(1)))
</button>

in render we check if there is moreQuestions. If not, we then convert state answers to binary number string. Because ReasonML don’t have JS Array Join method, we must use Bucklescript’s Js library (Js.Array.joinWith) prepend binary prefix to it (“0b” or “0B”) and pipe it to int_of_string function which will convert prefixed string to decimal number. Then we use that number to pattern-match our way to correct Hoolooskop sign.


render: self => {

let nextQuestionIndex = Array.length(self.state.answers);

let moreQuestions = nextQuestionIndex < Array.length(Data.questions);
let resultDecimalNumber = ! moreQuestions ? "0b0" ++ Js.Array.joinWith("", self.state.answers) |> int_of_string :

(-1);

let resultSign =

! moreQuestions ?

switch (resultDecimalNumber) {

| 0

| 1 => Data.filozof

| 2

| 3 => Data.emotivac

| 4

…..

one more thing we needed to do is to use Facebook API (FB.UI). We initialized FB in our index html and needed to bind to external JS libraries, so we use Bucklescript:

type fB;

[@bs.val] external fB : fB = "FB";

[@bs.send.pipe: fB] external fb_ui : 'a => unit = "ui";

and then just call fb_ui on click event:

fb_ui( { "method": "share_open_graph", ……..

Rest of it is mostly JSX, and our switch from JQuery to Reason is done.With it’s strong typing, type inference, functional features, nice compiler error messages, first-class files and some other things, there is no reason not to try Reason and ReasonReact.

https://reasonml.github.io/
https://bucklescript.github.io/
https://reasonml.github.io/reason-react/

Dejan Tasic

2018-04-25T09:13:55+00:00