Pattern Matching, Type Parameters, Exceptions, Loops, Modules, and BuckleScript This is of a where I will help you make sense of ReasonML and all of its syntax and semantics. I will go through everything from basic to declaring in ReasonML. Part 2 3 part series datatypes functions Make sure that you read and of this series before going further. They are all connected. Part 1 Part 2 Pattern Matching using Switch Pattern matching is one of the best features of the language. It mainly does two things: Check for a certain structure of a value. Extract parts of a value. With pattern matching, we can do many great things like piping multiple patterns into a single case! Thanks to structural equality, pattern matching works well with data structures like tuples, lists, variants, and records. Pattern Matching Tuple # switch (rajat) {| ("Learn ReasonML", false) => "It's Awesome"| ("Learn ReasonML", true) => "It really is awesome"}; But this will make our app exhaustive. We need to use to match the unmatched values for this type. Using a name instead of an underscore allows us to extract parts of the tuple. _ # switch (rajat) {| (_, true) => "Its Awesome"| (text, false) => "It really is awesome. " ++ text};- string = "It really is awesome. Learn ReasonML" Pattern Matching Lists In case of Lists, we can perform pattern matching on the exact list. # switch (["a", "b", "c"]) {| ["a", "b", "c"] => true| _ => false}; The best thing about pattern matching with Lists is that can be used to extract the first and last element of the List. ... # switch (["x", "y", "z"]) {| [head, ...tail] => print_endline(head)| [] => print_endline("Empty list")}; Pattern Matching Arrays When pattern matching arrays, we can only do so for arrays of specific lengths. The values in the array are matched using structural equality. We can either use an underscore or we can extract the array elements using a name. # switch ([|"a", "b", "c"|]) {| [|"a", "b", _|] => print_endline("a, b and something")| [|_, "x", "y"|] => print_endline("something, " ++ x ++ y)| _ => print_endline("An Array")}; Pattern Matching Records First, I will create a record by declaring the type and then bind it to a . name # type todo = { text: string, checked: bool};# let myTodo = { text: "Learn ReasonML", checked: true}; Now, I could extract the text by matching the exact value. But instead, I will try something else and extract the text using the name description. # switch (myTodo) {| {text, checked: true} => "It is awesome: " ++ text| {text, checked: false} => "You won't regret it!" ++ text};- : string = "It is awesome: Learn ReasonML" Pattern Matching Variants Lets create a variant called with tags and . hero DC Marvel # type hero = DC(string) | Marvel(string);# let dc = DC("Batman");# let marvel = Marvel("Iron Man"); Using pattern matching, I can check the tags and extract any part of the variant. # switch (dc) {| DC(text) => "I am " ++ text| Marvel(text) => "I am " ++ text};- : string = "I am Batman" If you want to match more than one item and return them as the result, you can do something like this: # switch ("Batman") {| "Superman" | "Batman" | "The Flash" => "DC Comics"| _ => "Marvel Comics"};- : string = "DC Comics" Type Parameters Types can also accept parameters. Parameters can be compared with generics in other languages. When you create a list, you first need to create a type list that receives a data type. Here, the data type is a type parameter. # let rajat: list(string) = ["Batman", "Superman"]; The compiler can even inverts the type parameter of a list. But why do we need this? Using type parameters, we can create the a new type that can accept as many parameters as we want. Basically, can turn into a function that takes in parameters and return a new type. type # type hero('a) = ('a, 'a);# let heroOne: hero(string) = ("Superman", "Clark Kent"); This way we can avoid repetition while creating more types. Also note that the type parameters are only valid if they start with a followed by a character or word. “`“, Mutability in let bindings bindings are immutable by default. Once a binding refers to a value, it cannot refer to anything else. But you can circumvent this issue by creating a new binding that has the same name and the previous binding. let shadows # let person = "Clark Kent";# print_endline(person); /* Prints "Clark Kent" */# let person = "Superman";# print_endline(person); /* Print "Superman" */ There is also a way to turn bindings mutable by using a reference to wrap the actual value. let # let foo = ref(5);let foo: ref(int) = {contents: 5}; Now if I want to change the data inside of , this is how I will do it: foo # foo := 6;- : unit = ()# foo;- : ref(int) = {contents: 6} The value of is changed from 5 to 6. To retrieve the value of reference, I need to use character. foo ^ # foo^;- : int = 6 Exceptions In Reason, Exception is a kind of variant that you get when trying to find something inside an empty list. # List.find(x => x == "Rajat", []);Exception: Not_found. That’s not all! You can create your own exceptions using the function. To catch exceptions in your app, use pattern matching. raise # raise(Not_found);Exception: Not_found.# try (raise(Not_found)) {| Not_found => "Oh Oh!"};= : string = "Oh Oh!" We can directly match exceptions in a expression using . switch exception # switch (List.find(x => x == "rajat", [])) {| name => "Obtained"| exception Not_Fount => "Not found"}; : string = "Not found"# switch (List.find(x => x == "rajat", ["rajat"])) {| item => "Obtained"| exception Not_found => "Not found"};- : string = "Obtained" There are not many uses for . In fact, you can instead use . exception option Loops For Loop loops are used to iterate from the first to the last value of a data structure. for # for (x in 1 to 5) {print_int(x * 2);print_string(" ");};2 4 6 8 10 - : unit = () The range needs to be valid and go from a lower value to a higher value. If you try to do it the other way, will not do anything. To make work in the reverse direction, replace with . for for to downto While Loop The loops will keep operating as long as the condition given is . while true # let x = ref(0);let x: ref(int) = { contents: 0};# while (x^ < 5) {print_int(x^);x := x^ + 1;};01234- : unit = () Modules Modules can be described as small blocks in your code. They allow us to encapsulate things like bindings and into logical entities. let types Every file in Reason is a module. This is why needs to be unique in each project. name Use the keyword to create a modules in your Reason project. Make sure that the name of your module is capitalized. module # module Rajat = {};`module Math` : { };# module Math = {let name = "rajat";let age = 24;};`module Math`: { let name: string; let age: int }; To access anything that is inside a module, use the notation. . # Rajat.name;- : string = "rajat"# Rajat.age;- : int = 24; notation is really helpful here as we can access types stored inside the module as well. This way, the compiler will only look at the current module or its parent module. . Reason also allows us to open a module’s definition and refer to its contents without prepending the name. To do so, we use the keyword. This will open the module globally and import its definition in the current scope. open BuckleScript Back in of this series, I had said that Reason can be compiled into JavaScript using something called Let’s see how this is actually done. Part 1 BuckleScript. First we need to install into our system. BuckleScript npm install -g bs-platform With this package installed, I can not only compile my code into JavaScript, but also into native binary code. Now I need to set up a new project using bs-platform bsb -init reason-project -theme basic-reason This command will create a new directory called in your system. If you take a look at the contents of this directory, you will notice that it shares a few similarities with a typical JavaScript project. reason-project The only unique thing here, is the file. This file is where we can configure the BuckleScript for this project. bsconfig.json If you look at the directory of this project, you will see that it contains a file. Let’s delete it and create a new file named . You can write any ReasonML code here and run the script using NPM/Yarn. This will compile any file with extension into a matching JavaScript file. So our file will compile into . src Demo.re Main.re build .re Main.re Main.bs.js You can run this JavaScript file using . node node src/Main.bs.js You can also using script to build it manually. This script will watch for file changes and compile accordingly. start What’s Next? This series should be enough to get you started with ReasonML. But if you still want to know more, take a look at Reason’s official Docs here: _sh_reasonml.github.io Quickstart · Reason You can also take a look at ’s Course on Egghead. It helped me a lot! Nik Graf _This course foremost will teach you about the syntax and semantics of the programming language Reason or also referred…_egghead.io Get Started with Reason I am Rajat S, Technical Content Writer at . Aspiring Coder who has a long way to go. A Die-Hard DC Comics Fan who loves Marvel Movies. Known for multi tasking. GeekyAnts Thanks for reading, and hopefully this was helpful! Please 👏 if you liked this post and follow me here and/or on to stay updated about new posts from me! Twitter