<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/"
    xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" version="2.0">
    <channel>
        
        <title>
            <![CDATA[ Reason - freeCodeCamp.org ]]>
        </title>
        <description>
            <![CDATA[ Browse thousands of programming tutorials written by experts. Learn Web Development, Data Science, DevOps, Security, and get developer career advice. ]]>
        </description>
        <link>https://www.freecodecamp.org/news/</link>
        <image>
            <url>https://cdn.freecodecamp.org/universal/favicons/favicon.png</url>
            <title>
                <![CDATA[ Reason - freeCodeCamp.org ]]>
            </title>
            <link>https://www.freecodecamp.org/news/</link>
        </image>
        <generator>Eleventy</generator>
        <lastBuildDate>Tue, 28 Jul 2026 03:52:54 +0000</lastBuildDate>
        <atom:link href="https://www.freecodecamp.org/news/tag/reason/rss.xml" rel="self" type="application/rss+xml" />
        <ttl>60</ttl>
        
            <item>
                <title>
                    <![CDATA[ How to get started with Reason ]]>
                </title>
                <description>
                    <![CDATA[ By Alireza Alidousti In this article, we will build a scheduler in Reason. Along the way, we will see how some of the core features of Reason interact with each other and make it an excellent fit for this project. You can find everything we cover her... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-get-started-with-reason-cef7ab40660/</link>
                <guid isPermaLink="false">66d45d983bc3ab877dae21ee</guid>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                    <category>
                        <![CDATA[ General Programming ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Reason ]]>
                    </category>
                
                    <category>
                        <![CDATA[ tech  ]]>
                    </category>
                
                    <category>
                        <![CDATA[ technology ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Thu, 26 Jul 2018 01:26:50 +0000</pubDate>
                <media:content url="https://cdn-media-1.freecodecamp.org/images/1*vigyGXRulD0Kou3OgnR6HQ.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Alireza Alidousti</p>
<p>In this article, we will build a scheduler in Reason. Along the way, we will see how some of the core features of Reason interact with each other and make it an excellent fit for this project. You can find everything we cover here in the <a target="_blank" href="https://github.com/Artris/reason-scheduler">repository</a>.</p>
<p>Most articles about Reason show how it works in ReasonReact. This makes sense, since Facebook developed Reason. In this article, however, I wanted to show how Reason shines as a language outside of ReasonReact.</p>
<p>This article assumes you have a basic to intermediate understanding of JavaScript. Some familiarity with Functional Programming wouldn’t hurt either.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*vigyGXRulD0Kou3OgnR6HQ.png" alt="Image" width="800" height="400" loading="lazy">
_[pixelated background with Imagemagick](https://reasonml.github.io/img/reason.svg" rel="noopener" target="_blank" title=""&gt;reason.svg converted to png with Imagemagic, &lt;a href="https://stackoverflow.com/a/506662" rel="noopener" target="<em>blank" title=")</em></p>
<h3 id="heading-why-choose-reason">Why choose Reason?</h3>
<p>Reason is a functional language, that encourages immutability, provides an inferred static type system, and compiles down to JavaScript. Let’s take a closer look:</p>
<ol>
<li>Reason and OCaml share the same semantics. And so the functional programming constructs available in OCaml such as pattern matching and currying directly translate to Reason.</li>
<li>In Reason, almost always you don’t have to write down the types — the compiler infers the types for you. For example, the compiler sees this <code>() =&gt; {1 +</code> 1} as a function that takes <code>a u</code>nit (no argument) and returns <code>an</code> int.</li>
<li>Most constructs in Reason are immutable. <code>List</code> is immutable. <code>Array</code> is mutable but has fixed size. Adding a new element to an array returns a copy of the array extended with the new element. <code>Record</code>s (similar to JavaScript objects) are immutable.</li>
<li><a target="_blank" href="https://bucklescript.github.io/">BuckleScript</a> compiles Reason down to JavaScript. You can work with JavaScript in your Reason code and use your Reason modules in JavaScript.</li>
</ol>
<p>Reason brings the benefits of a strongly typed language to a JavaScript at a low cost. You should definitely read the <a target="_blank" href="https://reasonml.github.io/docs/en/what-and-why.html">What and Why</a> section of the documentation, as it provides more context into the language and its features.</p>
<h3 id="heading-some-resources-to-help-you-get-started">Some resources to help you get started</h3>
<ol>
<li><a target="_blank" href="https://reasonml.github.io/docs/en/quickstart-javascript.html">Reason’s official docs</a> are simple and to the point</li>
<li><a target="_blank" href="http://reasonmlhub.com/exploring-reasonml/toc.html">Exploring ReasonML</a>, a book by Dr. Axel Rauschmayer, explores Reason in a more practical way</li>
<li><a target="_blank" href="https://bucklescript.github.io/docs/en/interop-overview.html">BuckleScript docs</a> talks in detail about interoperability with JavaScript and OCaml</li>
</ol>
<p>In this article, we will explore how different concepts in Reason such as Modules, Statements, Variable Bindings and Immutability work together. Whenever I introduce a new concept or syntax, I will link to the related docs and articles.</p>
<h3 id="heading-the-big-picture">The big picture</h3>
<p>This tutorial was inspired by <a target="_blank" href="https://github.com/node-schedule/node-schedule">Node Schedule</a>, a scheduler for Node.js that uses a single timer at all times. You can learn more about how Node Schedule works <a target="_blank" href="https://medium.com/artris/lazy-jar-scheduling-recurring-events-3e7dd7d246cc">here</a>.</p>
<p>Today we are going to create a scheduler in Reason that uses a single timer at all times. We will use our scheduler to execute recurring jobs. This project is just large enough to demonstrate some of the key concepts in Reason.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*XUqFXUvLLLVLQl1AJ844ow.png" alt="Image" width="800" height="464" loading="lazy">
<em>The Big Picture :P</em></p>
<p>To achieve this, we will define two modules — a Heap and a Scheduler.</p>
<p>Heap is an implementation of a priority queue. It keeps the jobs in the order they should be executed next. The key of a heap element is the next invocation time of the job.</p>
<p>Scheduler is composed of a heap and is responsible for updating the timer and executing the jobs by the specified recurrence rules.</p>
<ol>
<li>When a job executes, the scheduler will remove the job from the queue, calculates its next invocation time, and inserts the job back to the queue with its updated invocation time.</li>
<li>When a new job is added, the scheduler checks the next invocation time of the root (head / the job that will be executed next). If the new job should be executed before the head, the scheduler updates the timer.</li>
</ol>
<h3 id="heading-heap-module">Heap module</h3>
<p>The API of a priority queue defines:</p>
<ol>
<li>Inserting a new element to the queue with a key representing its priority</li>
<li>Extracting the element with the highest priority</li>
<li>Size of the queue</li>
</ol>
<p>Heap performs <code>insert</code> and <code>extract</code> operations in order <code>O(log(n))</code> where <code>n</code> is the size of the queue.</p>
<p><em>Note: We will talk about algorithm complexity in the last section of the article. If you’re not comfortable with algorithm complexity, you can ignore the last section.</em></p>
<p>If you’re not comfortable with the Heap data structure or need a refresher, I recommend watching the following lecture from <a target="_blank" href="https://ocw.mit.edu/courses/electrical-engineering-and-computer-science/6-006-introduction-to-algorithms-fall-2011/">MIT OCW 6006 course</a>. In the remaining of this section, we will implement the pseudocode outlined in the <a target="_blank" href="https://ocw.mit.edu/courses/electrical-engineering-and-computer-science/6-006-introduction-to-algorithms-fall-2011/lecture-videos/MIT6_006F11_lec04.pdf">lecture notes</a> of 6006.</p>
<h4 id="heading-defining-the-types-used-by-the-heap-module">Defining the types used by the heap module</h4>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*PyY92n6VujArlyYJRKb4Cw.png" alt="Image" width="800" height="193" loading="lazy">
<em>heapElement</em></p>
<p><code>heapElement</code> defines a <a target="_blank" href="https://reasonml.github.io/docs/en/record.html">record</a> type. Similar to a JavaScript object, you can access record fields by name. <code>{ key: 1, value: "1" }</code> creates a value of type <code>heapElement(int, string)</code>.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*x6t4tuT9L5mwr2LAQbM13A.png" alt="Image" width="800" height="193" loading="lazy">
<em>Heap.t</em></p>
<p><code>t('a, 'b)</code> is another record type and represents the Heap. This is the return type of our <code>create</code> function and the last parameter passed to all the other functions in the public API of our heap module.</p>
<p>To maintain the max heap property, Heap only needs to compare the keys of the elements in the array. Hence, we can hide the type of key from the Heap by providing a comparison function <code>compare</code> that returns true when its first argument has a higher priority than the second one.</p>
<p>This is the first time we see <code>ref</code>. <code>ref</code> is Reason’s way for supporting <a target="_blank" href="https://reasonml.github.io/docs/en/mutation.html">mutations</a>. You can have a <code>ref</code> to a value and update that <code>ref</code> to point to a new value by using the <code>:=</code> operator.</p>
<p><a target="_blank" href="http://2ality.com/2018/01/lists-arrays-reasonml.html">Arrays</a> in Reason are mutable — You can update a value at a specific index. However, they have a fixed length. To support addition and extraction our heap needs to hold onto a <code>ref</code> to an array of heap elements. If we don’t use a reference here, we will end up having to return a new heap after every addition and extraction. And the modules that depend on the heap need to keep track of the new heap.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*-p7C-2gEoHXi3e5GJlpACw.png" alt="Image" width="800" height="131" loading="lazy">
<em>EmptyQueue exception</em></p>
<p><code>[exception](https://reasonml.github.io/docs/en/exception.html)</code> can be extended with new constructors. We will <code>raise</code> <code>EmptyQueue</code> exception later in the <code>extract</code> and <code>head</code> functions in the heap module.</p>
<blockquote>
<p>Exceptions are all of the same type, <code>exn</code>. The <code>exn</code> type is something of a special case in the OCaml type system. It is similar to the variant types we encountered in Chapter 6, Variants, except that it is open, meaning that it's not fully defined in any one place. — <a target="_blank" href="https://v1.realworldocaml.org/">RealWorldOcaml</a></p>
</blockquote>
<h4 id="heading-signature">Signature</h4>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*o3X_FL51hhzAkipO7pmuLA.png" alt="Image" width="800" height="414" loading="lazy">
<em>Heap signature</em></p>
<p>By default, all the bindings (variable assignments) in a <a target="_blank" href="http://2ality.com/2017/12/modules-reasonml.html">module</a> are accessible everywhere even outside the module where they are defined. <code>signature</code> is the mechanism by which you can hide the implementation specific logic and define an API for a module. You can define a signature in a file with the same name as the module ending with .<code>rei</code> suffix. For example you can define the signature for the <code>Heap.re</code> in the <code>Heap.rei</code> file.</p>
<p>Here, we are exposing the definition of <code>heapElement</code> so the users of the Heap module can use the value returned by <code>head</code> and <code>extract</code>. But we are not providing the definition for <code>t</code> our heap type. This makes <code>t</code> an <a target="_blank" href="http://2ality.com/2017/12/modules-reasonml.html#abstract-types-hiding-internals">abstract type</a> which ensures that only functions within the Heap module can consume a heap and transform it.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*CFt90fE1yZP_eerExQXMWA.png" alt="Image" width="800" height="199" loading="lazy">
<em>Heap initializer</em></p>
<p>Every function except <code>create</code> takes as argument a heap. <code>create</code> takes a comparison function and creates an empty <code>Heap.t</code> that can be consumed by the other functions in the Heap module.</p>
<h4 id="heading-helper-functions">Helper functions</h4>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*xsWmdX09mFB9m9PY6a0F5g.png" alt="Image" width="800" height="476" loading="lazy">
<em>Helper functions</em></p>
<p><code>parent</code> is a function that takes a single argument — index. It returns <code>None</code> when the index is <code>0</code>. index <code>0</code> indicates the root of the tree, and the root of a tree doesn’t have a parent.</p>
<p><code>left</code> and <code>right</code> return the index of the left and the right child of a node.</p>
<p><code>swap</code> takes two indexes <code>a</code> and <code>b</code> and an array <code>queue</code>. It then swaps the values in the index <code>a</code> and <code>b</code> of the <code>queue</code>.</p>
<p><code>key</code> simply returns the key field of a <code>heapElement</code> at the specified index in the queue.</p>
<p><code>size</code> returns the length of the queue</p>
<h4 id="heading-add">Add</h4>
<p><code>add</code> is one of the primary functions we exposed in the <code>heap</code> signature. It takes a value and a key representing the priority of the value to insert into the queue. We will use this function later in the <code>Scheduler</code> module to add new jobs to our execution queue.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*u6pNMpi_mXftOAQjj72P1Q.png" alt="Image" width="800" height="460" loading="lazy">
<em>fix up</em></p>
<p><code>let rec</code> lets us define <a target="_blank" href="https://reasonml.github.io/docs/en/function.html#recursive-functions">recursive</a> functions. With <code>rec</code> you can refer to the function name inside the function body.</p>
<p>We defined <code>key</code> as a function that takes a <code>queue</code> and <code>index</code> as arguments. With the declaration <code>let key = key(queue)</code> we are <a target="_blank" href="https://reasonml.github.io/docs/en/let-binding.html#bindings-are-immutable">shadowing</a> <code>key</code> by <a target="_blank" href="https://reasonml.github.io/docs/en/function.html#currying">partially applying</a> the helper function <code>key</code> we defined previously.</p>
<p>When you provide a subset of the arguments to a function, it returns a new function that takes the remaining arguments as input — this is known as <a target="_blank" href="https://reasonml.github.io/docs/en/function.html#currying">currying</a>.</p>
<p>The arguments you provided are available to the returned function. Since <code>queue</code> is fixed in <code>fix_up</code>, we partially apply it to the <code>key</code> function to make our code more <a target="_blank" href="https://en.wikipedia.org/wiki/Don%27t_repeat_yourself">DRY</a>.</p>
<p>You can use <code>&lt;cas[e&gt;](https://reasonml.github.io/docs/en/pattern-matching.html#when-clauses); when &lt;c</code>ondition&gt; to specify additional conditions in pattern matching. The value bind<code>ings</code> in the case are available to the expressio<code>n fo</code>llowing when (in <code>our e</code>xample p_ind is a<code>vailable in compare(key(index),</code> key(p_ind)). Only when the condition is satisfied we execute the associated statemen<code>t</code> after the =&gt;.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*iCjD0S2bmy2RETedIvpEzw.png" alt="Image" width="800" height="275" loading="lazy">
<em>add</em></p>
<p><code>add</code> concatenates a new element to the end of the queue. If the new element has higher priority than its parent, it is violating the max heap property. <code>fix_up</code> is a recursive function that restores the max heap property by moving the new element up in the tree (pairwise swapping with its parent) until it reaches the root of the tree or its priority is lower than its parent.</p>
<p><code>fix_last</code> is just wrapper around <code>fix_up</code> and calls it with the index of the last element in the queue.</p>
<p><code>heap.queue^</code> is how we access the value <code>ref</code> references.</p>
<p><code>[||]</code> is the array literal syntax for an empty array.</p>
<h4 id="heading-extract">Extract</h4>
<p><code>extract</code> removes the element with the highest priority (in our case, the element with the smallest key) from the queue and returns it. <code>extract</code> removes the head of the queue by first swapping it with the last element in the array. This introduces a single violation of the max heap property at the root/head of the queue.</p>
<p>As described in the lecture, <code>heapify</code> — also known as <a target="_blank" href="https://en.wikipedia.org/wiki/Heap_(data_structure)">sift-down</a>— fixes a single violation. Assuming the left and right subtrees of node <code>n</code> satisfy the max heap property, calling <code>heapify</code> on <code>n</code> fixes the violation.</p>
<p>Each time <code>heapify</code> is called, it finds the <code>max_priority_index</code> index of the highest priority element between the heapElements at the <code>index</code>, <code>left(index)</code>, and the <code>right(index)</code>. If the <code>max_priority_index</code> is not equal to the <code>index</code>, we know there is still a violation of the max heap property. We swap the elements at the <code>index</code> and <code>max_priority_index</code> to fix the violation at <code>index</code>. We recursively call <code>heapify</code> with the <code>max_priority_index</code> to fix the possible violation we might create by swapping the two elements.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*h-3PqzJSyfruTGXgBdaKZg.png" alt="Image" width="800" height="553" loading="lazy">
<em>heapify</em></p>
<p><code>index</code> is an <code>int</code> representing the root of a subtree that violates the max heap property, but its subtrees satisfy the property. <code>compare</code> is the comparison function defined with the heap. <code>queue</code> is an array that holds the heap elements.</p>
<p><code>[if](https://reasonml.github.io/docs/en/if-else.html)</code> <a target="_blank" href="https://reasonml.github.io/docs/en/if-else.html">statements</a> in Reason like the other expressions evaluate to a value. Here the <code>if</code> statements evaluate to an <code>int</code> that represents which index was smaller in the comparison.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*fiHB42uHbI8KsPxBQaxZTQ.png" alt="Image" width="800" height="481" loading="lazy">
<em>extract</em></p>
<p><code>extract</code> pattern matches against <code>queue</code> (the array not the reference).</p>
<p><code>[|head|]</code> only matches an array with a single element.</p>
<p>When the queue is empty <code>[||]</code> we raise the <code>EmptyQueue</code> exception we defined previously. But why? Why don’t we return <code>None</code> instead? Well this is a matter of preference. I prefer to <code>raise</code> an exception, because when I use this function, I will get a <code>heapElement</code> and not a <code>option(heapElement)</code>. This saves me pattern matching against the returned value of the <code>extract</code>. The caveat is that you need to be careful when you use this function, making sure the <code>queue</code> is never empty.</p>
<p>When we have more than one element, we swap the first and the last element of the queue, remove the last element and call <code>heapify</code> on the first element (the root of the tree).</p>
<h3 id="heading-testing">Testing</h3>
<p>We use <code>bs-jest</code> — BuckleScript bindings for <code>Jest</code> — to write tests. <code>Jest</code> is a testing framework created by Facebook that comes with Built-in mocking library and code coverage reports.</p>
<ol>
<li><a target="_blank" href="https://github.com/glennsl/bs-jest">https://github.com/glennsl/bs-jest</a></li>
<li><a target="_blank" href="https://facebook.github.io/jest/docs/en/getting-started.html">https://facebook.github.io/jest/docs/en/getting-started.html</a></li>
</ol>
<p>Follow the instructions in <a target="_blank" href="https://github.com/glennsl/bs-jest#installation">bs-jest</a> to set up <code>Jest</code>.</p>
<p>Make sure to add <code>@glennsl/bs-jest</code> to <code>bs-dev-dependencies</code> in your <code>bsconfig.json</code>. Otherwise BuckleScript won’t find the <code>Jest</code> module and your build will fail.</p>
<p>If you’re writing your test cases in a directory other than <code>src</code> you have to specify it in the <code>sources</code> in the <code>bsconfig.json</code> for the BuckleScript compiler to pick them up.</p>
<h3 id="heading-testing-synchronous-functions">Testing synchronous functions</h3>
<p>With the <code>Heap</code> module in place and <code>Jest</code> installed, we are ready to write our first test case.</p>
<p>To test our <code>Heap</code> module, we will do a heap sort.</p>
<ol>
<li>create a heap</li>
<li>insert elements into the heap</li>
<li>use the <code>extract</code> operation to remove the elements in the ascending order</li>
</ol>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*VITeahvFmnplQfFoCcpgWQ.png" alt="Image" width="800" height="723" loading="lazy">
<em>Heap sort test</em></p>
<p><code>open Jest</code> opens the module so we can refer to the bindings available in the <code>Jest</code> module without prepending them with <code>Jest.</code>. For example, instead of writing <code>Jest.expect</code> we can just write <code>expect</code>.</p>
<p>We use <code>let {value: e1} =</code> to destructure the value returned by <code>extract</code> and create an alias <code>e1</code> for <code>value</code> — <code>e1</code> is now bound to the <code>value</code> field of the value returned by <code>extract</code>.</p>
<p>With the<code>|&amp;</code>g<a target="_blank" href="http://2ality.com/2017/12/functions-reasonml.html#the-reverse-application-operator">t; pipe opera</a>tor we can create a composite function and apply the resulting function immediately on an input. Here we simply pass the result of calli<code>ng exp</code>ect wi<code>th (e1, ...,</code> e9) to t<code>he toEq</code>ual function.</p>
<h3 id="heading-scheduler-module">Scheduler module</h3>
<p>Scheduler uses the Heap module to maintain a list of recurrent jobs sorted by their next invocation time.</p>
<h4 id="heading-lets-define-the-types-used-in-the-scheduler-module">Let’s define the types used in the Scheduler module</h4>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*M8mc6n7IKLQO3WSHugkrxQ.png" alt="Image" width="800" height="190" loading="lazy">
<em>recurrence</em></p>
<p><code>recurrence</code> is a <a target="_blank" href="https://reasonml.github.io/docs/en/variant.html">Variant</a> type. Any value of the <code>recurrence</code> type can either be a <code>Second</code>, <code>Minute</code>, or an <code>Hour</code>. <code>Second</code>, <code>Minute</code> and <code>Hour</code> are the constructors for the <code>recurrence</code>. You can invoke a constructor like a normal function and get back a value of the Variant type. In our case, if you call <code>Second</code> with an int you get back a value of type <code>recurrence</code>. You can pattern match this value with <code>Second(number_of_seconds)</code> to access the argument that was passed to the <code>Second</code> constructor.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*VFEqg9AK0jp47yiNb9w5iA.png" alt="Image" width="800" height="190" loading="lazy">
<em>job</em></p>
<p><code>job</code> is a <a target="_blank" href="https://reasonml.github.io/docs/en/record.html">record type</a>. <code>period</code> is of type <code>recurrence</code> and indicates the delay between each execution of a job. <code>invoke</code> is a function that takes <code>unit</code> (no argument) and returns <code>unit</code> (no result). <code>invoke</code> is the function that gets executed when the job runs.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*UPPSJx7GxuMOdNN83JUiUw.png" alt="Image" width="800" height="190" loading="lazy">
<em>Scheduler.t</em></p>
<p><code>t</code> is a record type representing the scheduler. A scheduler holds onto a <code>queue</code> of jobs sorted by their next invocation time. <code>timer_id</code> references the <code>timerId</code> for the first job in the <code>queue</code> — the job that will be invoked first.</p>
<h4 id="heading-interop">Interop</h4>
<p>You can invoke JavaScript functions from within Reason. There are different ways of doing this:</p>
<ol>
<li>you can use BuckleScript bindings if available, such as <code>Js.log</code>, and <code>[Js.Global.setTimeout](https://bucklescript.github.io/bucklescript/api/Js.Global.html)</code></li>
<li>declare an <code>external</code> such as <code>[@bs.val] external setTimeout</code></li>
<li>execute raw JavaScript code with <code>[%raw ...]</code></li>
</ol>
<p>Bindings for most JavaScript functions is provided by the BuckleScript. For example, <code>[Js.Date.getTime](https://bucklescript.github.io/bucklescript/api/Js.Date.html#VALgetTime)</code> takes a <code>Js.Date.t</code> — a <code>date</code> value — and returns the number of milliseconds since epoch. <code>Js.Date.getTime</code> is the binding for the <code>getTime</code> method of the the JavaScript Date object. <code>Js.Date.getTime</code> returns a <code>float</code> value.</p>
<p>Using bucklescript bindings is exactly the same as using user-defined modules. You can read more about the available bindings <a target="_blank" href="https://bucklescript.github.io/docs/en/stdlib-overview">here</a>. For the rest of this section we will focus on <code>external</code> and <code>[%raw ...]</code>.</p>
<h4 id="heading-external">external</h4>
<p>With <code>[external](https://bucklescript.github.io/docs/en/intro-to-external.html)</code> you can bind a variable to a JavaScript function. Here for example we are binding <code>setTimeout</code> variable to JavaScript’s setTimeout global function.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*YmF0EZ_kc_ShonlkILaxeg.png" alt="Image" width="800" height="184" loading="lazy">
_setTimeout and clearTimeout definition in [BuckleScript docs](https://bucklescript.github.io/docs/en/bind-to-global-values.html#abstract-type" rel="noopener" target="<em>blank" title=")</em></p>
<p><code>setTimeout</code> returns a <code>float</code>, an identifier that we can pass to <code>clearTimeout</code> to cancel the timer. The only function that uses the value returned by the <code>setTimeout</code> is <code>clearTimeout</code>. So we can define the value returned by <code>setTimeout</code> to have an <a target="_blank" href="https://bucklescript.github.io/docs/en/bind-to-global-values.html">abstract type</a>. This ensures that only a value returned by <code>setTimeout</code> can be passed to <code>clearTimeout</code>.</p>
<h4 id="heading-raw">[%raw …]</h4>
<p><code>new Date.getTime()</code> in JavaScript returns an integer Number. <a target="_blank" href="https://www.w3schools.com/js/js_numbers.asp">Numbers in JavaScript are 64bit long</a>. <code>[int](https://reasonml.github.io/docs/en/integer-and-float.html#integers)</code> <a target="_blank" href="https://reasonml.github.io/docs/en/integer-and-float.html#integers">in Reason are only 32bit long</a>. This is a problem!</p>
<p>In Reason, we can work with the returned value of <code>new Date.getTime()</code> by expecting it to be <code>Float</code>. This is actually the expected return type of <code>[Js.Date.getTime](https://bucklescript.github.io/bucklescript/api/Js.Date.html#VALgetTime)</code> provided by BuckleScript.</p>
<p>Instead, let’s use <code>[%raw ...]</code> and create an abstract type <code>long</code> similar to what we did for <code>setTimeout</code>. In doing this, we are hiding the implementation of <code>long</code>. Our Reason code can pass values of type <code>long</code> around, but it can’t really operate on them. For this we are defining a set of helper bindings that take values of type <code>long</code> and delegate the computation to raw JavaScript expressions.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*ZRlUB2r52RGmC-OTO4VCfg.png" alt="Image" width="800" height="209" loading="lazy">
<em>working with JavaScript values</em></p>
<p>We can define a JavaScript expression with <code>[[%raw ...]](https://bucklescript.github.io/docs/en/embed-raw-javascript.html)</code>. Here we are defining an <a target="_blank" href="https://bucklescript.github.io/docs/en/bind-to-global-values.html#abstract-type">abstract type</a> <code>long</code> and a set of functions that consume and return values of type <code>long</code>. The type of all the expressions is specified in the <code>let</code> bindings.</p>
<p><code>time_now</code> returns the number of milliseconds since epoch.</p>
<p>We use <code>sum</code> to calculate the next invocation time of a job, by passing in the result of <code>time_now</code> and an <code>int</code> representing how many milliseconds from now the job should be executed.</p>
<p>We can compute how long from now a job will be invoked by <code>subtract</code>ing the invocation time of a job from <code>time_now</code>. The result of <code>subtract</code> is passed to the <code>setTimeout</code>.</p>
<p><code>has_higher_priority</code> compares two invocation times. This is the comparison function we use to initialize our Heap.</p>
<h4 id="heading-invocation">Invocation</h4>
<p>At any point in time, we only have a single timer that expires when the first job in the queue should run. When the timer expires, we need to do some cleanup. When the timer expires, we should</p>
<ol>
<li>extract the first job from the queue</li>
<li>calculate its next invocation time (a new key for the job)</li>
<li>insert the job back into the queue with its updated key</li>
<li>look at the head of the queue to find the job that should be executed next and</li>
<li>create a new timer for this job</li>
</ol>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*DO8Jffa0o3kOz7iewxbxbg.png" alt="Image" width="800" height="371" loading="lazy">
<em>helpers</em></p>
<p><code>wait</code> takes a period — a value of type <code>recurrence</code> — and returns an int representing how many milli-seconds a job has to wait before getting executed again. We pass the value returned by <code>wait</code> to the <code>setTimeout</code>.</p>
<p><code>next_invocation</code> calculates the next invocation time of a job. <code>time_now</code> returns a <code>long</code> value. <code>sum</code> takes in a <code>long</code> and an <code>int</code> value and returns a <code>long</code> value. <code>sum</code> adds the two number by calling the JavaScript <code>+</code> operator on its arguments.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*aDR8VZdEHsqnbVjyw3lbyQ.png" alt="Image" width="800" height="337" loading="lazy">
<em>Invoking a job</em></p>
<p><code>execute</code> is a recursive function that is responsible for executing the job and doing the cleanup. It captures the scheduler in a closure and returns a function that can be invoked when the timer expires.</p>
<p>In the first three lines, we remove the job with the highest priority (lowest key or closest invocation time) and insert it back into the queue with its next invocation time.</p>
<p>We then go on to create a new timer for the job at the head of the queue (the next job that should be executed after this invocation). We update the <code>timer_id</code> reference to point to the new <code>timerId</code>.</p>
<p>Finally, we call the <code>invoke</code> field of the job to perform the specified task.</p>
<h4 id="heading-add-a-new-job">Add a new job</h4>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*CUaRpxz-tRRsmTibKHsCkQ.png" alt="Image" width="800" height="666" loading="lazy">
<em>adding a new job</em></p>
<p>When the <code>queue</code> is empty, adding a new job is simple. We create a timer that expires at the next invocation time of the job.</p>
<p>The more interesting case is when the queue is not empty! We can have two situations here. Either the head of the <code>queue</code> has a key greater than the next invocation time of the job or not.</p>
<p>The first case is when the head of the <code>queue</code> has a key less than or equal to the next invocation time of the job. This is the case when the new job needs to be executed before the current timer. In this case, we need to cancel the timer by calling <code>clearTimeout</code> with the <code>timer_id</code> and create a new timer that will expire at the next invocation time of the new job.</p>
<p>In the other case, because the new job needs to be executed after the current timer expires, we can just insert the new job in the <code>queue</code>.</p>
<h3 id="heading-testing-asynchronous-functions">Testing asynchronous functions</h3>
<p>All the functions in the heap module are <a target="_blank" href="https://medium.com/@siddharthac6/javascript-execution-of-synchronous-and-asynchronous-codes-40f3a199e687">synchronous</a>. For example, when you call <code>add</code>, you are blocked until a new heapElement has been added to the queue. When <code>add</code> returns, you know that the heap has been extended with the new element.</p>
<p>The functions in the scheduler, on the other hand, have <a target="_blank" href="https://medium.com/@siddharthac6/javascript-execution-of-synchronous-and-asynchronous-codes-40f3a199e687">asynchronous</a> side effects. When you <code>add</code> a new job to the scheduler, the scheduler adds the job to its queue and returns. Later, according to the <code>recurrence</code> rule the job gets invoked. Your code doesn’t wait for the job to get invoked, and continues executing.</p>
<p>Now, lets write a test case to ensure that when a job is added to the scheduler, it gets invoked according to its recurrence rule.</p>
<p>To do this we will</p>
<ol>
<li><code>add</code> a job to the scheduler to be executed every second. This job increments a <code>ref(int)</code> counter.</li>
<li>create a <code>Promise</code> that gets resolved after 4s</li>
<li>return a <code>Jest.assertion</code> promise that expects the counter to have been incremented 4 times.</li>
</ol>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*5w1tMJibX4SAKV_1Aa98wA.png" alt="Image" width="800" height="664" loading="lazy">
<em>Test Scheduler add</em></p>
<p>We can use <code>testPromise</code> to test promises. <code>testPromise</code> expects a <code>Js.Promise.t(Jest.assertion)</code>. Look at the last line of the test case.</p>
<p><code>Scheduler.Second(1)</code> indicates we want our job to execute every second.</p>
<p><code>counter</code> is a <code>ref</code> and everytime <code>invoke</code> is called, it gets incremented.</p>
<p><code>promise</code> is a <code>[Js.Promise.t](https://reasonml.github.io/docs/en/promise.html)</code> that will get resolved after 4s. Notice that we are waiting for 4.1s to make sure the last call to the <code>invoke</code> has finished executing. Otherwise, we might resolve the promise when we have only incremented the counter three times.</p>
<p>You can use <code>|&amp;</code>gt; to chain promises. In our exampl<code>e, prom</code>ise will resolve with the value of the counter after 4s. This value is provided as t<code>he co</code>unt to the function passed to t<code>he Js.Promise.th</code>en_.</p>
<h3 id="heading-optimize">Optimize</h3>
<p>We implemented our Heap and Scheduler modules similar to what we would have done in JavaScript. In doing so, we have reduced the performance of the functions operating on the heap such as <code>add</code> and <code>extract</code> to <code>O(n)</code>.</p>
<p>We know Array in Reason has a fixed length. Everytime we add a new job or delete one, the size of our Array will change and therefore a new copy will be created. We can fix this by creating a dynamic array module that implements <a target="_blank" href="https://ocw.mit.edu/courses/electrical-engineering-and-computer-science/6-006-introduction-to-algorithms-fall-2011/lecture-videos/lecture-9-table-doubling-karp-rabin/">table doubling</a>.</p>
<p>I have created a version of Heap and Dynamic Array if you’re interested in the <a target="_blank" href="https://github.com/Artris/algorithms">implementation</a>, however, I think this would be outside the scope of this article. So for now we focus on optimizing the Scheduler by calling operations that cost <code>O(n)</code> less frequently.</p>
<p>There are two places in the Scheduler where we call <code>Heap.add</code> and <code>Heap.extract</code> — when adding a new job and when executing a job.</p>
<p>We can’t help <code>Scheduler.add</code> but we can fix the performance of <code>Scheduler.execute</code>. The <code>execute</code> function doesn’t need to call <code>extract</code> or <code>add</code> since the size of our queue before and after <code>execute</code> should be the same.</p>
<p>Let’s introduce a new function to our Heap Signature. <code>decrease_root_priority</code> reduces the priority of the root of the Heap. We can use this new function to update the root key to its next invocation time without first extracting the head of the queue and adding it back with its updated invocation time.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*fZg1ncv_dVYefFbr39tJdA.png" alt="Image" width="800" height="257" loading="lazy">
<em>execute optimized</em></p>
<p><code>decrease_root_priority</code> takes the new priority for the root, checks to make sure the new priority is less than the current priority of the root, and delegates the actual work to a helper function <code>update_priority</code>.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*pb-1W-PBteiPwhpSroPCbA.png" alt="Image" width="800" height="359" loading="lazy">
<em>decrease root priority</em></p>
<p><code>update_priority</code> can decrease or increase the priority of any element in a Heap in <code>O(log(n))</code>. It checks whether the new priority violates the max heap property with respect to the children of a node or its parent. When we increase the priority of a node, we might be violating the max heap property of the node with respect to its parent and so we <code>fix_up</code>. When we decrease the priority of a node, we might be violating the max heap property with respect to its children and so we call <code>heapify</code> to fix the possible violation.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*kPgoqtoJBe-Lt8zoZRTP2A.png" alt="Image" width="800" height="379" loading="lazy">
<em>decrease priority</em></p>
<h3 id="heading-next-steps">Next steps</h3>
<p>This article is by far not a complete overview of the features of Reason. We have seen many of the language constructs, but haven’t explored them in detail. There are also features that have been left out, such as functors and objects. I strongly recommend you to read the <a target="_blank" href="https://reasonml.github.io/docs/en/overview">documentation</a> or <a target="_blank" href="http://reasonmlhub.com/exploring-reasonml/index.html">Exploring ReasonML and functional programming</a> to know what’s available to you before jumping to coding.</p>
<p>The complete source code for what we covered today is available in the <code>master</code> branch of the <a target="_blank" href="https://github.com/Artris/reason-scheduler">https://github.com/Artris/reason-scheduler</a></p>
<p>If you want to practice, I encourage you to add <code>remove</code> functionality to the scheduler. In specific, extend the signature of the <code>Scheduler</code> with</p>
<ul>
<li><code>type jobId</code> and</li>
<li><code>let remove = (t, jobId) =&gt; u</code>nit</li>
</ul>
<p>I also encourage you to add test cases for the functions exposed in the signature of the <code>Heap</code> and <code>Scheduler</code> modules.</p>
<p>The test cases for all the functions in the <code>Heap</code> and <code>Scheduler</code> module as well as an implementation for the <code>remove</code> functionality is available in the <a target="_blank" href="https://github.com/Artris/reason-scheduler/tree/solutions">solutions</a> branch.</p>
<h3 id="heading-attribution">Attribution</h3>
<p>I would like to thank the Reason/BuckleScript community for providing detailed documentation. And Dr. <a target="_blank" href="http://2ality.com/">Axel Rauschmayer</a> for <a target="_blank" href="http://reasonmlhub.com/exploring-reasonml/toc.html">Exploring ReasonML</a> book and many interesting articles on Reason.</p>
<p>Code snippets were generated using <a target="_blank" href="https://carbon.now.sh/">carbon.now.sh</a>.</p>
<p>I’d also like to thank <a target="_blank" href="https://twitter.com/graziettahof">Grace</a>, <a target="_blank" href="https://twitter.com/sami_elfeki">Sami</a>, <a target="_blank" href="https://twitter.com/freestellar">Freeman</a>, and <a target="_blank" href="https://github.com/preetpalS">Preetpal</a> who helped review this article.</p>
 ]]>
                </content:encoded>
            </item>
        
    </channel>
</rss>
