HomeMachine LearningMachine Learning DIYCommon JavaScript Idioms in ReasonML

Common JavaScript Idioms in ReasonML

Explore the differences and similarities in idioms used in JavaScript and ReasonML.

Learning a new programming language is difficult, especially when you switch from a dynamically typed language like JavaScript, to something more sane and typed, like Reason.

Furthermore, learning a more functional language has certain difficulties. You need to have a completely different mindset when facing the same problems and sometimes you need to use another mental pattern in order to find a more elegant solution.

Sure, you could try to use exactly the same approach as you would with JavaScript, but then you would miss out all the fun 😉

Enough talking, let’s get to some examples and we’ll clearly see what we are talking about!

Removing a value from a list

Well, first of all, the default list in JavaScript (the native Array) is mutable, but sometimes we need to operate over them in a side-effect free manner, say for example, in a reducer:

case “REMOVE_LIST_ELEMENT”:
  return [...xs.slice(0, xs.indexOf(index)), ...xs.slice(xs.indexOf(index + 1))];

This is a pretty common pattern and even our prophet, Dan Abramov, has used it on his infamous Redux egghead tutorial 👼 How could we achieve the same in Reason? 🤔 Lo and behold!

xs->Belt.List.keep(x => x != item);

Side note: Belt is the default standard library to be used with Reason when targeting JavaScript, it is very performant and uses several optimizations under the hood to enforce blazingly fast JS as an output! 🚀

🤯 Okay so what is going on here? Well, as you might have noticed right now, the keep() function is similar to JavaScript’s filter() function, the not so subtle difference is that Reason’s List type is immutable by default, which is pretty cool. We would need to use Immutable.js or seamlessly-immutable or Mori.js to have something similar in JavaScript, whereas in Reason it is built-in into the language!

Also, where are our beloved triple equals (===)!? Well, you might be surprised to know this, but in Reason, the equality operator (==) actually works as it should and allows you to compare structural equality! This is a game changer for me, no need to keep sticking to the old pattern of finding the index of the item we want to remove, we can actually compare it with != and filter out the elements we don’t want from our list… achieving that way exactly the same thing as in our JavaScript example, but in a more elegant/functional/immutable way! 👏

Find an element in a list and then use it

Another mundane thing that we do in our daily lives is looking up items and use them somewhere else, you know, this code you have probably typed a thousand times already…

const city = cities.find(x => x.id === cityId);

Pretty normal stuff, nothing interesting here except for the fact that we are so used to JavaScript not being able to compare objects, that we don’t even notice that sometimes we use unique identifiers or other stuff to find what we are looking for as the language itself can’t help us in those situations 😄

let city = cities->Belt.List.getBy(x => x.id == cityId);

Okay, that makes sense, besides the fact that the find method is called getBy in Reason, which is no big deal here, except is it? Well my friend, the best part is yet to come…

Let’s have a look at the type signature of the getBy function. You would see that it is: list('a) => ('a => bool) => option('a). This means that you cannot use this code as you would in JavaScript, because the actual return type of the function is an option type! 🤯 Why is this amazing?

How many times have you thought that your typical JavaScript find() method could fail? How many times have you programmed defensively adding default values like find(f) || { value: 'default value' } to make sure that your code does not break unexpectedly? Yes, we all do it (when we remember to) but, be honest… do you always have this in mind when you code? In Reason, whenever we would like to use our returned option value we’d have to pattern match over it:

switch(city) {
  | None => Js.log(“not found!”)
  | Some(city) => Js.log(“found:” ++ city.name)
}

Yes, this is one of the many advantages of a type safe language, you cannot forget about error checking because the language does not allow you to make these kinds of mistakes! (You would get a beautiful error from the compiler saying something like a string was expected but instead it received an option(string)). This is awesome. 😎

Map over a list and use the indexes

On some occasions, you might want to map over an array and use the index of every given element, this is a very widespread practice in everyday JavaScript. One example of this is when in React we have to give some elements their own key (and we don’t have anything better to use as a key 😉):

<ul>
  {[“foo”, “bar”, “baz”].map((x, key) => <li key={key}>{x}</li>)}
</ul>

That sounds familiar, doesn’t it? 😜 Well, interestingly enough, the default Belt.List.map function does not have such information as the index for the elements in the key so, how would we solve this?

<ul>
  {[|“foo”, “bar”, “baz”|]
  ->Belt.Array.mapWithIndex((key, x) => {let key = string_of_int(key); <li key>{ReasonReact.string(x)}</li>})
  ->ReasonReact.array}
</ul>

Neat! So for different purposes we have different functions in Belt, most of them very similar to what we would use in JavaScript, and some of them with slightly different changes in their API. Generally speaking, when we use a list operation function and we need the index for the element, we will have the equivalent [Function]WithIndex function, in this case, mapWithIndex!

Another nice thing that we have in Reason that you might have noticed in the code above is JSX punning! We no longer need to specify key={key}, whenever we have a variable which name matches a given JSX prop, we can use this shorthand syntax and it will work! 🎉 (I REALLY miss this feature when working on React in JavaScript 😭)

What We Learned

These were some of the things I learned on my Reason journey and I’m really excited about it, hope you found it useful and that it helped you as well to see some of the goodies of the language and maybe hopefully you are now a bit more hyped and will share it with the world! 🌍

And you? What is your favorite feature of Reason? What other mind blowing moments have you experienced or common idioms you missed/discovered coming from JavaScript? Let me know in the comments! ☺️

Shameless self promotion: 🙃 I’ll keep writing about the things I learn and some other interesting stuff related to functional programming so if you don’t want to miss out, stay tuned and follow me on Twitter! @FlavioCorpa 👋

Thanks to G2i for publishing this post. For those who are unfamiliar, G2i is a hiring platform run by engineers that matches clients with pre-vetted React, React Native, GraphQL, and native iOS/Android focused engineers you can trust.

“This article was originally published at G2i

 

 

Most Popular